⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 misc-watchdog-1.c

📁 本程序是在arm9200平台上实现看门狗的驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
				//CLK Low
				AT91_SYS->PIOC_CODR=FM_SCK;
				udelay(10);
				//CLK High
				AT91_SYS->PIOC_SODR=FM_SCK;
				udelay(5);
				}

		udelay(20);

		cmd=add2;
		for( i=0;i<=7;i++ )
				{
				//CMD Output
				bit=( cmd<<i )&0x80;
				if( bit )
						AT91_SYS->PIOC_SODR=FM_SO;
	      else
						AT91_SYS->PIOC_CODR=FM_SO;
				udelay(5);

				//CLK Low
				AT91_SYS->PIOC_CODR=FM_SCK;
				udelay(10);
				//CLK High
				AT91_SYS->PIOC_SODR=FM_SCK;
				udelay(5);
				}

		udelay(20);

		for( j=0;j<len;j++ )
				{
				//Read DATA
				for( i=1;i<=8;i++ )
						{
						read_data=read_data<<1;
						//CLK High
						AT91_SYS->PIOC_SODR=FM_SCK;
						udelay(10);
						//CLK Low
						AT91_SYS->PIOC_CODR=FM_SCK;

						//Data in
						if( (AT91_SYS->PIOC_PDSR&FM_SI) != 0 )
								read_data|=1;
						else
								read_data&=0xfe;
						udelay(10);
						}
				p[j]=read_data;
				}

		AT91_SYS->PIOD_SODR=FM_CS1;

//printk("\nread data= %d,%d,%d,%d,%d,%d,%d,%d\n",p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7] );
		return( j );
}

//-----------------------------------------------------------------------------------------------------
//----------------write data to Fram 2
//-----------------------------------------------------------------------------------------------------
static void write_to_fm_2( unsigned char add1,unsigned char add2,unsigned char len,unsigned char *p )
{
		int i,j;
		unsigned char bit;
		unsigned char cmd=0x05;
		unsigned char read_data=0;

		//write write-enabe command
		cmd=0x06;
		AT91_SYS->PIOD_SODR=FM_CS1;
		AT91_SYS->PIOD_CODR=FM_CS2;
		udelay(10);
		for( i=0;i<=7;i++ )
				{
				//CMD Output
				bit=( cmd<<i )&0x80;
				if( bit )
						AT91_SYS->PIOC_SODR=FM_SO;
	      else
						AT91_SYS->PIOC_CODR=FM_SO;
				udelay(5);

				//CLK High
				AT91_SYS->PIOC_SODR=FM_SCK;
				udelay(10);
				//CLK Low
				AT91_SYS->PIOC_CODR=FM_SCK;
				udelay(5);
				}
		AT91_SYS->PIOD_SODR=FM_CS2;

		udelay(20);

		//write command
		cmd=0x02;
		AT91_SYS->PIOD_CODR=FM_CS2;
		udelay(10);
		for( i=0;i<=7;i++ )
				{
				//CMD Output
				bit=( cmd<<i )&0x80;
				if( bit )
						AT91_SYS->PIOC_SODR=FM_SO;
	      else
						AT91_SYS->PIOC_CODR=FM_SO;
				udelay(5);

				//CLK High
				AT91_SYS->PIOC_SODR=FM_SCK;
				udelay(10);
				//CLK Low
				AT91_SYS->PIOC_CODR=FM_SCK;
				udelay(5);
				}

		udelay(20);

		cmd=add1;
		AT91_SYS->PIOD_CODR=FM_CS2;
		udelay(10);
		for( i=0;i<=7;i++ )
				{
				//CMD Output
				bit=( cmd<<i )&0x80;
				if( bit )
						AT91_SYS->PIOC_SODR=FM_SO;
	      else
						AT91_SYS->PIOC_CODR=FM_SO;
				udelay(5);

				//CLK High
				AT91_SYS->PIOC_SODR=FM_SCK;
				udelay(10);
				//CLK Low
				AT91_SYS->PIOC_CODR=FM_SCK;
				udelay(5);
				}

		udelay(20);

		cmd=add2;
		for( i=0;i<=7;i++ )
				{
				//CMD Output
				bit=( cmd<<i )&0x80;
				if( bit )
						AT91_SYS->PIOC_SODR=FM_SO;
	      else
						AT91_SYS->PIOC_CODR=FM_SO;
				udelay(5);

				//CLK High
				AT91_SYS->PIOC_SODR=FM_SCK;
				udelay(10);
				//CLK Low
				AT91_SYS->PIOC_CODR=FM_SCK;
				udelay(5);
				}
	
		udelay(20);

		for( j=0;j<len;j++ )
				{
				cmd=*p;
				p++;
				for( i=0;i<=7;i++ )
						{
						//CMD Output
						bit=( cmd<<i )&0x80;
						if( bit )
								AT91_SYS->PIOC_SODR=FM_SO;
			      else
								AT91_SYS->PIOC_CODR=FM_SO;
						udelay(5);

						//CLK High
						AT91_SYS->PIOC_SODR=FM_SCK;
						udelay(10);
						//CLK Low
						AT91_SYS->PIOC_CODR=FM_SCK;
						udelay(5);
						}
				}

		AT91_SYS->PIOD_SODR=FM_CS2;
		udelay(20);
}

//------------------------------------------------------------------------------------------------------------
//------------read data from Fram 2
//------------------------------------------------------------------------------------------------------------
static unsigned char read_from_fm_2( unsigned char add1,unsigned char add2,unsigned char len,unsigned char *p )
{
		int i,j;
		unsigned char bit;
		unsigned char cmd=0x05;
		unsigned char read_data=0;
		unsigned char read[10];

		//write read command
		cmd=0x03;
		AT91_SYS->PIOD_SODR=FM_CS1;
		AT91_SYS->PIOD_CODR=FM_CS2;
		udelay(10);
		for( i=0;i<=7;i++ )
				{
				//CMD Output
				bit=( cmd<<i )&0x80;
				if( bit )
						AT91_SYS->PIOC_SODR=FM_SO;
	      else
						AT91_SYS->PIOC_CODR=FM_SO;
				udelay(5);

				//CLK Low
				AT91_SYS->PIOC_CODR=FM_SCK;
				udelay(10);
				//CLK High
				AT91_SYS->PIOC_SODR=FM_SCK;
				udelay(5);
				}

		udelay(20);

		cmd=add1;
		for( i=0;i<=7;i++ )
				{
				//CMD Output
				bit=( cmd<<i )&0x80;
				if( bit )
						AT91_SYS->PIOC_SODR=FM_SO;
	      else
						AT91_SYS->PIOC_CODR=FM_SO;
				udelay(5);

				//CLK Low
				AT91_SYS->PIOC_CODR=FM_SCK;
				udelay(10);
				//CLK High
				AT91_SYS->PIOC_SODR=FM_SCK;
				udelay(5);
				}

		udelay(20);

		cmd=add2;
		for( i=0;i<=7;i++ )
				{
				//CMD Output
				bit=( cmd<<i )&0x80;
				if( bit )
						AT91_SYS->PIOC_SODR=FM_SO;
	      else
						AT91_SYS->PIOC_CODR=FM_SO;
				udelay(5);

				//CLK Low
				AT91_SYS->PIOC_CODR=FM_SCK;
				udelay(10);
				//CLK High
				AT91_SYS->PIOC_SODR=FM_SCK;
				udelay(5);
				}

		udelay(20);

		for( j=0;j<len;j++ )
				{
				//Read DATA
				for( i=1;i<=8;i++ )
						{
						read_data=read_data<<1;
						//CLK High
						AT91_SYS->PIOC_SODR=FM_SCK;
						udelay(10);
						//CLK Low
						AT91_SYS->PIOC_CODR=FM_SCK;

						//Data in
						if( (AT91_SYS->PIOC_PDSR&FM_SI) != 0 )
								read_data|=1;
						else
								read_data&=0xfe;
						udelay(10);
						}
				p[j]=read_data;
				}

		AT91_SYS->PIOD_SODR=FM_CS2;

//printk("\nread data= %d,%d,%d,%d,%d,%d,%d,%d\n",p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7] );
		return( j );
}

static struct my_data_of_fram do_fm( struct my_data_of_fram mm )
{
		if( mm.flag_of_which_fram==0x01 )//fram 1
				{
				if( mm.flag_of_command==0x01 )//write
						{
						write_to_fm_1( mm.add1,mm.add2,mm.len,mm.data_buffer );
						}
				else
				if( mm.flag_of_command==0x02 )//read
						{
						read_from_fm_1( mm.add1,mm.add2,mm.len,mm.data_buffer );
						}
				}
		else
		if( mm.flag_of_which_fram==0x02 )//fram 2
				{
				if( mm.flag_of_command==0x01 )//write
						{
						write_to_fm_2( mm.add1,mm.add2,mm.len,mm.data_buffer );
						}
				else
				if( mm.flag_of_command==0x02 )//read
						{
						read_from_fm_2( mm.add1,mm.add2,mm.len,mm.data_buffer );
						}
				}
		return mm;
}

static void watchdog_ping(void)
{
		if( aaa==0x00 )
				{
				AT91_SYS->PIOA_CODR=USER_LED1;
				aaa=0xff;
				}
		else
				{
				AT91_SYS->PIOA_SODR=USER_LED1;
				aaa=0x00;
				}
}


/*
 * Allow only one person to hold it open
 */
 //wdt设备打开操作
static int wdt977_open(struct inode *inode, struct file *file)
{
//		if(timer_alive)  //计数器,当wdt被启用后进制重复打开!
// 				return -EBUSY;
		#ifdef CONFIG_WATCHDOG_NOWAYOUT
	  		MOD_INC_USE_COUNT;
		#endif
		timer_alive++;

		//max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog.
		if( timeout>255 )
    		timeout=255;

//		printk("Watchdog: active, current timeout %d min.\n",timeout);
		return 0;
}

//wdt的关闭操作
static int wdt977_release(struct inode *inode, struct file *file)
{
 /*
  * Shut off the timer.
  *  Lock it in if it's a module and we defined ...NOWAYOUT
  */

		#ifndef CONFIG_WATCHDOG_NOWAYOUT
				lock_kernel();

		timer_alive=0;
		unlock_kernel();

//		printk("Watchdog: shutdown.\n");
		#endif
//		printk("Watchdog: shutdown.\n");
		timer_alive=0;
		
		return 0;
}

ads7843_ts_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{

//		DECLARE_WAITQUEUE(wait, current);
//		struct ads7843_ts *ts = filp->private_data;
		char *ptr = buffer;
		int err = 0;
/*
		add_wait_queue(&ts->read_wait, &wait);
		while (count >= sizeof(struct ts_event)) 
				{
				err = -ERESTARTSYS;
				if (signal_pending(current))
						break;

				if (ads7843_ts_evt_pending(ts)) 
						{
						struct ts_event *evt = ads7843_ts_evt_get(ts);

						err = copy_to_user(ptr, evt, sizeof(struct ts_event));
						ads7843_ts_evt_pull(ts);

						if (err)
								break;

						ptr += sizeof(struct ts_event);
						count -= sizeof(struct ts_event);
						continue;
						}

				set_current_state(TASK_INTERRUPTIBLE);
				err = -EAGAIN;
				if (filp->f_flags & O_NONBLOCK)
						break;
				schedule();
				}
		current->state = TASK_RUNNING;
		remove_wait_queue(&ts->read_wait, &wait);
 */
		return ptr == buffer ? err : ptr - buffer;
}


//在这里wdt的写就是“喂狗”操作
static ssize_t wdt977_write(struct file *file, const char *data, size_t len, loff_t *ppos)
{
		//max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog.
		if (timeout>255)
    		timeout=255;

 /*
  * Refresh the timer.
  */
 
 //we have a hw bug somewhere, so each 977 minute is actually only 30sec
 //as such limit the max timeout to half of max of 255 minutes...
// if (timeout>126)
//     timeout = 126;
		return 1;
}

struct wd
	{
	int a;
	int b;
	int c;
	};




static struct wd wd2;
//wdt的ioctl函数
static int watchdog_ioctl( struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg )
{
		int i, new_margin;
		struct my_time m_time;
		struct my_date m_date;
		struct my_data_of_fram my_fram1;
		int ret=0;

		switch( cmd )
				{
				case 10:
						m_date=my_read_date();
						return copy_to_user((void *) arg, &m_date, sizeof(m_date));
				case 11:
						m_time=my_read_time();
						return copy_to_user((void *) arg, &m_time, sizeof(m_time));
				case 12:
						if (copy_from_user(&m_date, (struct my_date *) arg, sizeof(m_date)))
								ret = -EFAULT;
						write_rtc_date( m_date );
						return 0x00;
				case 13:
						if (copy_from_user(&m_time, (struct my_time *) arg, sizeof(m_time)))
								ret = -EFAULT;
						write_rtc_time( m_time );
						return 0x00;

				case 14:
						if (copy_from_user(&my_fram1, (struct my_data_of_fram *) arg, sizeof(my_fram1)))
								ret = -EFAULT;
						my_fram1=do_fm( my_fram1 );
						if( my_fram1.flag_of_command==0x02 )
								return copy_to_user( (void *) arg, &my_fram1, sizeof(my_fram1) );

						return my_fram1.len;
						
  			case WDIOC_GETSTATUS:
  			case WDIOC_GETBOOTSTATUS:
  			case WDIOC_KEEPALIVE:
   					watchdog_ping();
   					return 0;

			  default:
   					return -ENOTTY;
 				}
}

//定义fops结构,开发驱动对struct file_operations 再熟悉不过了。
//函数的入口很简单,这就是为什么采用misc的原因了
static struct file_operations wdt977_fops=
{
		owner:  	THIS_MODULE,
		write:  	wdt977_write,
		read:			ads7843_ts_read,
		open:  		wdt977_open,
	  ioctl:  	watchdog_ioctl,
		release: 	wdt977_release,
};

//根据misc驱动模型要求,定义miscdevice 结构体
static struct miscdevice wdt977_miscdev=
{
		minor:	WATCHDOG_MINOR,
		name:		"wd",
		fops:		&wdt977_fops,
};

static int __init nwwatchdog_init(void)
{
//		if (!machine_is_netwinder())
//				return -ENODEV;

		AT91_SYS->PIOA_PER=USER_LED1;//用作通用IO
		AT91_SYS->PMC_PCER = 0x0000001c;
		AT91_SYS->PIOA_OER=USER_LED1;//用作输出
		AT91_SYS->PIOA_SODR=USER_LED1;//输出高电平


		AT91_SYS->PIOD_PER=TOUCH_CS1|TOUCH_CS2|FM_CS1|FM_CS2;
		AT91_SYS->PIOD_OER=TOUCH_CS1|TOUCH_CS2|FM_CS1|FM_CS2;
		AT91_SYS->PIOD_SODR=TOUCH_CS1|TOUCH_CS2|FM_CS1|FM_CS2;

		AT91_SYS->PIOC_PER=FM_SCK|FM_SI|FM_SO;
		AT91_SYS->PIOC_OER=FM_SCK|FM_SO;
		AT91_SYS->PIOC_ODR=FM_SI;
		AT91_SYS->PIOC_SODR=FM_SO;
		AT91_SYS->PIOC_CODR=FM_SCK;

		AT91_SYS->PIOB_PER=MY_RTC_CS|MY_RTC_SCK|MY_RTC_IO;
		AT91_SYS->PIOB_OER=MY_RTC_CS|MY_RTC_SCK|MY_RTC_IO;
		AT91_SYS->PIOB_CODR=MY_RTC_CS|MY_RTC_SCK|MY_RTC_IO;

		misc_register(&wdt977_miscdev);   //注册设备驱动
//	  printk("NetWinder Watchdog sleeping.\n");
		return 0;
}

static void __exit nwwatchdog_exit(void)
{
		misc_deregister(&wdt977_miscdev);   //卸载设备驱动
}

EXPORT_NO_SYMBOLS;

module_init(nwwatchdog_init);
module_exit(nwwatchdog_exit);
//MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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