ndac_drv.c

来自「华颐公司的以AT91RM9200为CPU的9200F 开发板在linux开发环」· C语言 代码 · 共 174 行

C
174
字号
/*****************************************************************************
;Institue of Automation, Chinese Academy of Sciences
;www.hyesco.com
;Description: DAC driver on Linux for H9200F
;Date:			2005-11-17		
;Author:		
;E_mail:		
*****************************************************************************/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h> //including irq number

#include <asm/arch/AT91RM9200_SYS.h>

/*
DAC基地址,与硬件电路相关,H9200F的DAC电路包含一个通道,
地址为:0x7000,0060,由NCS6选择,当用户改变跳线时,基地
址需要做相应的修改。
*/ 
#define EBI_BASE_ADDRESS	0x70000000L
#define EBI_OFFSET_ADDRESS	0x60
#define DA_sys_offset		EBI_BASE_ADDRESS + EBI_OFFSET_ADDRESS
#define DA_Size			0x40

struct  _DA_ADDR 
{
	//CH1和CH0间隔4×8=32字节,对应于偏移地址0x60和0x80,但系统目前仅用到0x60。
	unsigned int   AT91C_DAC_CH1;
	unsigned int   Reserved0[7];
	unsigned int   AT91C_DAC_CH0;
}; 

typedef struct  _DA_PARA
{
	int     Channel;
	int	Adc_value;
} AT91_DA_PARA; 


//全局变量,常量;
static int major=249;
static char s_name[]="ndac";
struct _DA_ADDR *Dac_Addr;
int DA_CH,DA_value;

//函数定义;
static int s_open(struct inode * s_node,struct file * s_file);
static int s_release(struct inode * s_node,struct file * s_file);
static int s_write(struct file*s_file, const char*w_buf,int len,loff_t* loff);
static int DA_mem();

struct file_operations Tmint_fops_DAC=
{
	write  :	(void(*)) s_write,
	open   :	(void(*)) s_open,
	release:	(void(*)) s_release,
 };

//地址空间申请与检测函数;
static int DA_mem()
{
		
	//申请内存区域,以检测该地址空间是否被使用;
	if (!request_mem_region(DA_sys_offset,DA_Size,"DAC_REG"))
		printk("Error request mem DAC_REG \n"); 
    		
	//进行内存区域的映射,把物理地址映射为逻辑地址;  
	Dac_Addr = ioremap(DA_sys_offset,DA_Size); 
	return 0;	
};

//延时函数;
void Delay(unsigned int x)
{
	unsigned int i,j,k;
	for(i=0;i<=x;i++)
		for(j=0;j<2;j++)
			for(k=0;k<2;k++);
}

//初始化模块函数;
static int __init s_init_module(void)
{
	int retv;
	//注册模块;
	retv=register_chrdev(major,s_name,&Tmint_fops_DAC);
	if(retv<0)
		{
		printk("<1>Register Fail!\n");
		return retv;
		}
	DA_mem();
	printk("init DAC module is ok!\n");
	return 0;
}

//清除模块函数;
static void __exit s_cleanup_module(void)
{
 	int retv;
 	
 	//注销模块;
	retv=unregister_chrdev(major,s_name);
 	
 	//取消内存区域映射;
	iounmap(Dac_Addr);
	
	//释放申请的内存区域;
	release_mem_region(DA_sys_offset,DA_Size);
	if(retv<0)
		{
    		printk("<1>ADC UnRegister Fail!\n");
   		return ;
		}
	printk("<1>DAC:Good Bye!\n");
}

//open函数
static int s_open(struct inode * s_node,struct file * s_file)
{
	MOD_INC_USE_COUNT;
	
	//定义EBI控制寄存器的读写参数,参考AT91RM9200用户手册P190;
	AT91_SYS->EBI_SMC2_CSR[6]= AT91C_SMC2_NWS| AT91C_SMC2_WSEN
		| AT91C_SMC2_TDF | AT91C_SMC2_BAT | AT91C_SMC2_DBW_16
		| AT91C_SMC2_RWHOLD|AT91C_SMC2_ACSS_3_CYCLES  ;
	
	return 0;
}

//write函数 
static int s_write(struct file*s_file, const char *w_buf,int len,loff_t* loff)
{
	AT91_DA_PARA dac_para;
				
	if(copy_from_user(&dac_para,w_buf,sizeof(AT91_DA_PARA)))	
		return -EFAULT;
	
	DA_CH    = dac_para.Channel;
	DA_value = dac_para.Adc_value;	
	
	switch(DA_CH)
      		{
        	case 0:
	        	Dac_Addr->AT91C_DAC_CH0=DA_value;    //选择通道A输出   
	           	break;
       		case 1:
             		Dac_Addr->AT91C_DAC_CH1=DA_value;    //选择通道B输出   
          	break;  
        	}	
	Delay(10);      		
  	return sizeof(unsigned int );
}

//release函数
static int s_release(struct inode * s_node,struct file * s_file)
{
	MOD_DEC_USE_COUNT;
	return 0;
}

module_init(s_init_module);
module_exit(s_cleanup_module);
MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?