引用的人家的驱动:led

 有很多朋友关心驱动,但更菜的菜鸟居多:)总结了一下 把I/O驱动改成个更简单的LED驱动吧
做的工作非常简单,就是让连在GPC0-GPC2上的LED顺序闪10下
目的就是演示一下驱动过程。

一 先补充一下基础知识 懂的朋友就不用看了

嵌入式驱动的概念
 
设备驱动程序是操作系统内核和机器硬件之间的接口,设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以像操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它主要完成的功能有:对设备进行初始化和释放;把数据从内核传送到硬件和从硬件读取数据;读取应用程序传送给设备文件的数据、回送应用程序请求的数据以及检测和处理设备出现的错误。
 
Linux将设备分为最基本的两大类:一类是字符设备,另一类是块设备。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了。字符设备以单个字节为单位进行顺序读写操作,通常不使用缓冲技术;块设备则是以固定大小的数据块进行存储和读写的,如硬盘、软盘等,并利用一块系统内存作为缓冲区。为提高效率,系统对于块设备的读写提供了缓存机制,由于涉及缓冲区管理、调度和同步等问题,实现起来比字符设备复杂得多。LCD是以字符设备方式加以访问和管理的,Linux把显示驱动看做字符设备,把要显示的数据一字节一字节地送往LCD驱动器。
 
Linux的设备管理是和文件系统紧密结合的,各种设备都以文件的形式存放在/dev目录下,称为设备文件。应用程序可以打开、关闭和读写这些设备文件,完成对设备的操作,就像操作普通的数据文件一样。为了管理这些设备,系统为设备编了号,每个设备号又分为主设备号和次设备号。主设备号用来区分不同种类的设备,而次设备号用来区分同一类型的多个设备。对于常用设备,Linux有约定俗成的编号,如硬盘的主设备号是3。Linux为所有的设备文件都提供了统一的操作函数接口,方法是使用数据结构struct file_operations。这个数据结构中包括许多操作函数的指针,如open()、close()、read()和write()等,但由于外设的种类较多,操作方式各不相同。Struct file_operations结构体中的成员为一系列的接口函数,如用于读/写的read/write函数和用于控制的ioctl等。打开一个文件就是调用这个文件file_operations中的open操作。不同类型的文件有不同的file_operations成员函数,如普通的磁盘数据文件,接口函数完成磁盘数据块读写操作;而对于各种设备文件,则最终调用各自驱动程序中的I/O函数进行具体设备的操作。这样,应用程序根本不必考虑操作的是设备还是普通文件,可一律当作文件处理,具有非常清晰统一的I/O接口。所以file_operations是文件层次的I/O接口。

二 开始写了
采用了在代码里加注释的方法,同时把几个文件上传了一下,喜欢的朋友可以下载当作模板。每个文件以==隔开
一共需要写写3个文件,1个驱动头文件,1个驱动文件,一个驱动测试用程序文件
分别是test.h,test.c和ledtest.c

简单说说驱动都做什么,怎么做
1 系统加载驱动
2 应用程序里打开设备(文件)
3 应用程序对设备操作
4 应用程序关闭设备(文件)
5 系统关闭设备

应用程序如何对设备操作?
记得C语言里怎么写文件吗?这里很相象的。对于一般的字符设备(还有块设备,网络设备等等)主要有3个函数(还有很多,可以看)llseek    read:    write:    ioctl:  这里只用ioctl:控制函数,当然也可以使用读写函数操作IO 口,但ioctl:似乎更适合。
具体实现可以看ledtest.c文件了。

test.c中主要有几个函数 分别负责初始化和清除,打开和关闭。以及ioctl对串口寄存器写一些数据。
初始化和清除,打开和关闭函数里都各有一句主要句,已经分别作了注释。只要记住就好了。

对寄存器操作就不单独说了,需要看44B0数据手册了。好了 剩下的看代码吧。
==============================
==========test.h==================
==============================

/****************************************Copyright (c)**************************************************
**                               FREE
**
**--------------File Info-------------------------------
** File Name: config.h
** Last modified Date:  2006-9-9
** Last Version: 1.0
** Descriptions: User Configurable File
**
**----------------------------------------------------
** Created By: ZLG CHENMINGJI
** Created date:   2006-9-9
** Version: 1.0
** Descriptions: First version
**
**-------------------------------------------------
** Modified by:MAMAJINCO
** Modified date:2006-9-9
** Version:1.0
** Descriptions:在此忠心感谢ZLG的模版 我的高质量编程意识起源于此
**
*****************************************************/
//防止重复包含此文件而设置的宏
#ifndef __CONFIG_H
#define __CONFIG_H

//包含必要的头文件
#i nclude <linux/config.h>
#i nclude <linux/module.h> //模块必须包含的头文件
#i nclude <linux/kernel.h>       /* printk()函数,用于向内核输出信息 */
#i nclude <linux/fs.h>           /* 很重要 其中包含了如file_opration等结构 此结构用于文件层接口 */
#i nclude <linux/errno.h>        /* 错误代码*/
#i nclude <asm/uaccess.h>
#i nclude <linux/types.h>
#i nclude <linux/mm.h>
#i nclude <asm/arch/s3c44b0x.h>

/********************************/
/*     应用程序配置             */
/********************************/
//以下根据需要改动
//定义主设备号 设备名称

#define LED_MAJOR_NR 231 //231~239 240~255都可以

#define DEVICE_NAME "led"               /* name for messaging */

#define SET_LED_OFF 0
#define SET_LED_ON 1

#endif
/************************                            End Of File
*********************************************************/


=============END===============

==============================
============test.c================
==============================

/*************Copyright (c)**************************
**                               FREE
**
**--------------File Info-----------------------------------------
** File Name: test.c
** Last modified Date:  2006-9-9
** Last Version: 1.0
** Descriptions: User Configurable File
**
**----------------------------------------------------
** Created By: ZLG CHENMINGJI
** Created date:   2006-9-9
** Version: 1.0
** Descriptions: First version
**
**--------------------------------------------------------
** Modified by:MAMAJINCO
** Modified date:2006-9-9
** Version:1.0
** Descriptions:在此忠心感谢ZLG的模版 我的高质量编程意识起源于此
**
***********************************************************/
#i nclude "test.h"//包含驱动头文件


/************************************************************
              function announce
******************************************************/
//以下是关键函数的声明
static int led_open(struct inode *inode, struct file *filp);
//打开设备时用的 linux把设备当作文件管理 设备最好在用的时候再打开 尽量不要提前
static int led_release(struct inode *inode, struct file *filp);
static int led_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                unsigned long param);
//控制函数 这里用于控制LED亮与灭
int  led_init(void);//注册时用的 注意 模块注册的越早越好
void led_cleanup(void);//卸载时用的

/*************************************************************
**                  "全局和静态变量在这里定义"        
**        global variables and static variables define here

/****************************************************************/

static struct file_operations LED_fops =        /* 前面基础部分提到的重要结构体了*/
{
    owner:      THIS_MODULE,

#if 0/*注意:#if 0-#endif里的代码是不编译的,但这里为了驱动模板讲解上的完整性仍然加上了*/
    llseek:     gpio_llseek,
    read:       gpio_read,
    write:      gpio_write,
#endif
    ioctl:      led_ioctl,//控制函数
    open:       led_open, //打开函数,打开文件时做初始化的
    release:    led_release,//释放函数,关闭时调用
};

               
/**************************************************************
** Function name: led_open
** Descriptions:  open device
** Input:inode:   information of device
**       filp:    pointer of file
** Output 0:      OK
**        other:  not OK
** Created by:    Chenmingji
** Created Date:  2006-9-9
**-------------------------------------------------------------
** Modified by:mamajinco
** Modified Date: 2006-9-9
**--------------------------------------------------------------
**************************************************************/
        static int led_open(struct inode *inode, struct file *filp)
{
 /*初始化放在OPEN里*/
 (*(volatile unsigned *)S3C44B0X_PCONC) &= 0xffffffc0;
 (*(volatile unsigned *)S3C44B0X_PCONC) |= 0xffffffd5; /*GPIO C口0~2 设置为输出*/

 (*(volatile unsigned *)S3C44B0X_PUPC) &= 0xffffffc0;/*GPIO C口0~2 设置为上拉*/

     MOD_INC_USE_COUNT;
     return 0;         
}

*********************************************************
** Function name: led_release
** Descriptions:  release device
** Input:inode:   information of device
**       filp:    pointer of file
** Output 0:      OK
**        other:  not OK
** Created by:    Chenmingji
** Created Date:  2006-9-9
**-----------------------------------------------------
** Modified by: mamajinco
** Modified Date: 2006-9-9
**--------------------------------------------------------
****************************************************/
        static int led_release(struct inode *inode, struct file *filp)
{
    MOD_DEC_USE_COUNT;
    return(0);
}

/****************************************************
** Function name: led_ioctl
** Descriptions:  IO control function
** Input:inode:   information of device
**       filp:    pointer of file
**       cmd:     command
**       arg:     additive parameter
** Output 0:      OK
**        other:  not OK
** Created by:    Chenmingji
** Created Date:  2006-9-9
**-------------------------------------------------------
** Modified by: mamajinco
** Modified Date: 2006-9-9
**----------------------------------------------------------
***********************************************************/
        static int led_ioctl(struct inode *inode, struct file *filp,
                       unsigned int cmd, unsigned long arg)
{
    if( arg > 2 )//判断IO是否属于0-2
 return -1;

    switch(cmd)
    {
        case 0://把ARG传来的IO口编号转换成寄存器数据,把相应IO口置低
         (*(volatile unsigned *)S3C44B0X_PDATC) |= 0x1 << arg;

             break;

        case 1://把ARG传来的IO口编号转换成寄存器数据,把相应IO口置高
  (*(volatile unsigned *)S3C44B0X_PDATC) &= 0x0 << arg;
             break;

        default:
  return -1;
  break;
    }
    return 0;
}

/**************************************************
** Function name: led_init
** Descriptions:  init driver
** Input:none
** Output 0:      OK
**        other:  not OK
** Created by:    Chenmingji
** Created Date:  2006-9-9
**------------------------------------------------
** Modified by: mamajinco
** Modified Date: 2006-9-9
**-----------------------------------------------------
*************************************************/
 int led_init(void)
{
    int  result;

    result = register_chrdev(231,"led",  &LED_fops);
/*关键语句 用于注册
** 注意!这是传统的注册方法 在2.4以上的linux版本中 加入了devfs设备文件系统 使注册更容易 但为了与大部分资料相**同 大家看的方便  这里仍然使用老方法*/
    if (result < 0) //用于异常检测
    {
        printk(KERN_ERR DEVICE_NAME ": Unable to get major %d/n", LED_MAJOR_NR ); //printk用于向内核输出信息
        return(result);
    }


    printk(KERN_INFO DEVICE_NAME ": init OK/n");
 
 return(0);
}

/*************************************************************
** Function name: led_cleanup
** Descriptions:  exit driver
** Input:none
** Output none
** Created by:    Chenmingji
** Created Date:  2006-9-9
**--------------------------------------------------------
** Modified by: mamajinco
** Modified Date: 2006-9-9
**-----------------------------------------------------
**************************************************/
        void led_cleanup(void)
{
    unregister_chrdev(231, "led"); //与register_chrdev配对使用 用于清楚驱动
}

/***********************************************************
**                            End Of File
****************************************************/


===============END=============

=====================================
=============ledtest.c===============
===================================

/*********************Copyright (c)**************************
**                               FREE
**
**--------------File Info----------------------------
** File Name: led.c
** Last modified Date:  2006-9-9
** Last Version: 1.0
** Descriptions: User Configurable File
**
**-------------------------------------------------------
** Created By: ZLG CHENMINGJI
** Created date:   2006-9-9
** Version: 1.0
** Descriptions: First version
**
**--------------------------------------------------------
** Modified by:MAMAJINCO
** Modified date:2006-9-9
** Version:1.0
** Descriptions:在此忠心感谢ZLG的模版 我的高质量编程意识起源于此
**
********************************************************/

#i nclude <stdio.h>
#i nclude <stdlib.h>
#i nclude <unistd.h>
#i nclude <fcntl.h>
#i nclude <sys/types.h>
#i nclude <sys/stat.h>

void delay(int delay)//延时用函数
{
 int i;
 for(;delay>0;delay--)
 {
  for(i=0 ; i < 5000 ; i ++);
  
 }
}

int main()
{
 int fd1;
 int j;

 fd1= open("/dev/led" , O_RDWR);/*打开设备,就象打开文件一样简单*/

 if(fd1 == -1)/*异常处理*/
 {
  printf ( "file can not be open" );
  return -1;
 }
 
 for (j =0 ; j< 10 ; j ++)/*重复10次*/
 {
  ioctl(fd1 , 1 , 0);/*GPC0上LED亮*/
  delay(1000);
  ioctl(fd1 , 0 , 0);/*GPC0上LED灭*/
  ioctl(fd1 , 1 , 1);/*GPC1上LED亮*/
  delay(1000);
  ioctl(fd1 , 0 , 1);/*GPC1上LED灭*/
  ioctl(fd1 , 1 , 2);/*GPC2上LED亮*/
  delay(1000);
  ioctl(fd1 , 0 , 2);/*GPC2上LED灭*/
  delay(1000);
 }
 
 close (fd1);/*关闭设备(文件)*/
 return 0;
  
}


===============END===============

 

三 驱动编译进内核
编译的中对于菜鸟来说需要需要注意几点
1 被打错字,包括上面的函数中也是!
就算各位扔砖头我也得说,因为编译进内核是很费时间的~~而且最重要的是对于菜鸟来说make的错误提示都是一道关,绝对不要自己给自己设置障碍!我们团队里就常有兄弟姐妹出现这样的错误,怎么看怎么对,尤其是从书上抄下来的命令和字符,l和1还有I你怎么分?最后一个是大写的i :)
2 不要用中文文件名 包括ABC(复件)
要不然MAKE出错
3 在各个现成的文件里修改的时候按照原有的格式修改 要不然菜鸟很难保证不犯低级错误
让我想起来了IBM的规律总结测试题:6 13 7 14 8 下一个数字是什么?

好了 开始修改!
===============START==============
uClinux-dist/linux-2.4.x/drivers/char/Makefile
----------------------------------------------
obj-$(CONFIG_C5471_WDT) += wdt_c5471.o之后加
obj-$(CONFIG_TEST) += led.o
================END============

=================START===========
uClinux-dist/linux-2.4.x/drivers/char/Config.in
-----------------------------------------
if [ "$CONFIG_CPU_S3C44B0X" = "y" ]; then
   bool 'Samsung S3C44B0X serial ports support' CONFIG_SERIAL_S3C44B0X之后加
   bool 'Test LED Driver' CONFIG_TEST
================END=================
=================START=============
uClinux-dist/linux-2.4.x/drivers/char/mem.c
-----------------------------------------
开头的地方扎堆加
#ifdef CONFIG_LEDTEST
extern void led_init(void);
#endif

int __init chr_dev_init(void)之后加
#ifdef CONFIG_TEST
 led_init();
#endif
================END==============
=================START============
uClinux-dist/vendors/Samsung/44B0/Makefile
-----------------------------------------
ttypc,c,3,12 ttypd,c,3,13 ttype,c,3,14 ttypf,c,3,15/之后加
/
led,c,231,0 /
================END==============


四 把程序编译进内核
没什么说的了,和过去写的简单的程序一样加 但这里再重复一次

================START============
uClinux-dist/user/Makefile
-----------------------------------------
扎堆加个下面
dir_$(CONFIG_USER_LEDTEST)                  += LEDtest
=================END===============
================START============
uClinux-dist/config/Configure.help
-----------------------------------------
扎堆加个下面
CONFIG_USER_LEDTEST
  Test the LED driver
=================END=============
================START================
uClinux-dist/config/Configure.in
-----------------------------------------
##############################
mainmenu_option next_comment
comment 'LED driver test PG'

bool 'LEDtest' CONFIG_USER_LEDTEST
endmenu

###############################
=================END=============

五 编译 烧写……省略200字 想看的看我写的helloworld编译笔记吧
六 下面的操作在板子上执行
1 cd /dev
2 ls
看见里面有个LED了吧?
3 cd /proc
4 cat devices
看见驱动列表吧?
led 231也应该在里面
5 LEDtest
在任何地方执行这个语句 就可以
之后看GPIO的C口电平吧:)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值