下面分析一下数字温度计DS1620的驱动程序。先从网上找到其数据手册,看看它的功能,再找到时序图片一下。这样有利于分析驱动,再套用上linux的驱动框架就可以了。
同样,先找驱动的入口和出口,看看他们都做了什么。
module_init(ds1620_init);
module_exit(ds1620_exit);
先来看一些常量的定义吧
/*
* arch/arm/include/asm/therm.h: Definitions for Dallas Semiconductor
* DS1620 thermometer driver (as used in the Rebel.com NetWinder)
*/
#ifndef __ASM_THERM_H
#define __ASM_THERM_H
/* ioctl numbers for /dev/therm */
#define CMD_SET_THERMOSTATE 0x53
#define CMD_GET_THERMOSTATE 0x54
#define CMD_GET_STATUS 0x56
#define CMD_GET_TEMPERATURE 0x57
#define CMD_SET_THERMOSTATE2 0x58
#define CMD_GET_THERMOSTATE2 0x59
#define CMD_GET_TEMPERATURE2 0x5a
#define CMD_GET_FAN 0x5b
#define CMD_SET_FAN 0x5c
#define FAN_OFF 0
#define FAN_ON 1
#define FAN_ALWAYS_ON 2
struct therm {
int hi;
int lo;
};
#endif
定义了一些常量寄存器的值:
/*Definitions for DS1620 chip */
#defineTHERM_START_CONVERT 0xee
#defineTHERM_RESET 0xaf
#defineTHERM_READ_CONFIG 0xac
#defineTHERM_READ_TEMP 0xaa
#defineTHERM_READ_TL 0xa2
#defineTHERM_READ_TH 0xa1
#defineTHERM_WRITE_CONFIG 0x0c
#defineTHERM_WRITE_TL 0x02
#defineTHERM_WRITE_TH 0x01
#defineCFG_CPU 2
#defineCFG_1SHOT 1
staticint__init ds1620_init(void)
{
intret;
structtherm th, th_start;
这个什么东东????
if(!machine_is_netwinder())
return-ENODEV;
这个是设置一些参数?复位,配置,停止转换。
ds1620_out(THERM_RESET,0, 0);
ds1620_out(THERM_WRITE_CONFIG,8, CFG_CPU);
ds1620_out(THERM_START_CONVERT,0, 0);
/*
* Trigger the fan to start by setting
* temperature high point low. This kicks
* the fan into action.
*/
ds1620_read_state(&th);
th_start.lo= 0;
th_start.hi= 1;
ds1620_write_state(&th_start);
msleep(2000);
ds1620_write_state(&th);
这里是注册一个混杂设备(混杂设备就是不知道如何归类的)
ret= misc_register(&ds1620_miscdev);
if(ret < 0)
returnret;
这里创建/proc文件系统节点,方便从/proc中获取信息,这样就不用写标准的测试程序了。
就不用走那套老的程序open(),read(),write(),close().
#ifdefTHERM_USE_PROC
proc_therm_ds1620= create_proc_entry("therm",0, NULL);
if(proc_therm_ds1620)
proc_therm_ds1620->read_proc= proc_therm_ds1620_read;
else
printk(KERN_ERR"therm:unable to register /proc/therm\n");
#endif
读取一下当前状态,输出一下信息。
ds1620_read_state(&th);
ret= cvt_9_to_int(ds1620_in(THERM_READ_TEMP, 9));
printk(KERN_INFO"Thermostat:high %i.%i, low %i.%i, "
"current%i.%i C, fan %s.\n",
th.hi >> 1, th.hi & 1 ? 5 : 0,
th.lo >> 1, th.lo & 1 ? 5 : 0,
ret >> 1, ret & 1 ? 5 : 0,
fan_state[netwinder_get_fan()]);
return0;
}
staticvoid__exit ds1620_exit(void)
{
移除/proc节点
#ifdefTHERM_USE_PROC
remove_proc_entry("therm",NULL);
#endif
注销混杂设备。
misc_deregister(&ds1620_miscdev);
}
再来看一下混杂设备的结构体及接口函数:
structmiscdevice {
intminor;
constchar*name;
conststructfile_operations*fops;
structlist_headlist;
structdevice*parent;