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

📄 pwm.c

📁 飞思卡尔的mx21处理器的pwm驱动程序源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if(gWriteCnt == 0)
		ret = 1; // no data
	else
		ret = 0; // processing data

	PK("<1>out pwm_read ----\n");
	return ret;
}

/******************************************************************************
 * Function Name: pwm_interrupt
 *
 *
 * Description: interrupt handler
 *
 * Modification History:
 * 	10 DEC,2001, 
 *****************************************************************************/
void pwm_interrupt()
{
U16	tmp16;
U32	status;

	PK("in pwm_interrupt ----\n");
	// clear status
	status = _reg_PWM_PWMC;

	// check end
	if(gWriteCnt < 0)
	{
		StopPwm();
		return;
	}

	if (gPwmMode == PWM_PLAY_MODE)
	{
		if(gDataLen == PWM_DATA_8BIT)
		{
			_reg_PWM_PWMS = (U32)(*gpWriteBufPtr8++);
			PK("<1>(%d) pwm_int: PWMS = 0x%8x\n", gWriteCnt, _reg_PWM_PWMS);

			gWriteCnt--;
		}
		else if(gDataLen == PWM_DATA_16BIT)
		{
			tmp16 = *gpWriteBufPtr8++;
			tmp16 |= (*gpWriteBufPtr8++ << 8);
			_reg_PWM_PWMS = (U32)tmp16;
			PK("<1>(%d) pwm_int: PWMS = 0x%8x\n", gWriteCnt, _reg_PWM_PWMS);

			gWriteCnt -= 2;
		}
	}

	PK("out pwm_interrupt ----\n");
	
}

static ssize_t pwm_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos)
{
	int ret = 0;

	PK("<1>in pwm_write ----\n");

	gWriteOk = 0;

	gpWriteBuf = kmalloc(count, GFP_KERNEL);
	if (!gpWriteBuf)
		goto out;
	gpWriteBufPtr8 = gpWriteBuf;

	if (copy_from_user(gpWriteBuf, buf, count))
	{
		ret = -EFAULT;
		goto out;
	}

	//write data to PWM
	gWriteCnt = count;
	PK("<1>pwm_write: count = %d\n", gWriteCnt);

	//enable IRQEN, PW
	_reg_PWM_PWMC |= 0x00000010;

	_reg_PWM_PWMS = 0x00000000;

	if(gPwmMode == PWM_PLAY_MODE)
	{
//		PK("before set IRQEN\n");
		_reg_PWM_PWMC |= 0x00000040;
		PK("PWMC1= 0x%08x\n", _reg_PWM_PWMC);
//               _reg_PWM_PWMS = 0x00000000;
	}
	else
	{
		_reg_PWM_PWMS = gSampleValue;
		_reg_PWM_PWMC |= 0x7f00;	// set prescaler to 128
		gpWriteBufPtr16 = (U16*)gpWriteBuf;

		gWriteCnt /= 2; //input size is 8bit size, need /2 to get 16bit size

		StartTimer(&pwmTimer);
	}

	PK("<1>pwm_write: PWMC = 0x%8x\n", _reg_PWM_PWMC);

out:

	PK("<1>out pwm_write ----\n");
  	return ret;
}


/******************************************************************************
 * Function Name: initpwm
 *
 * Input: 			:
 * Value Returned:	int	: Return status.If no error, return 0.
 *
 * Description: initialize PWM hardware
 *
 * Modification History:
 * 	10 DEC,2001, 
 *****************************************************************************/

static int __init initpwm()
{
	PK("<1>in initpwm ----\n");
	//	Init Port PE5 : PWMO
	_reg_CRM_PCCR1 |= 0x10000000;
	
	_reg_GPIO_DDIR(GPIOE) |= 0x00000020;
	_reg_GPIO_GIUS(GPIOE) &= ~0x00000020;
	_reg_GPIO_GPR(GPIOE) &= ~0x00000020;	

	PK("<1>out initpwm ----\n");
	return 1;
}

/******************************************************************************
 * Function Name: pwm_init
 *
 * Input: 		void	:
 * Value Returned:	int	: Return status.If no error, return 0.
 *
 * Description: device driver initialization
 *
 * Modification History:
 * 	10 DEC,2001, 
 *****************************************************************************/
 static devfs_handle_t devfs_handle;
#ifdef MODULE
int init_module(void)
#else
int __init pwm_init(void)
#endif
{
	int result;

	printk("PWM driver version 0.2.0\n");
	PK("<1>Init module\n");

	/* register our character device */

 	result = devfs_register_chrdev(0, MOD_NAME, &ts_fops);
 	if ( result < 0 )
 	{
		printk("pwm driver: Unable to register driver\n");
		return -ENODEV;
	}
	devfs_handle = devfs_register(NULL, "pwm", DEVFS_FL_DEFAULT,
				      result, 0,
				      S_IFCHR | S_IRUSR | S_IWUSR,
				      &ts_fops, NULL);   
	if( gMajor == 0 )
	{
		gMajor = result;
		printk("PWM major number = %d\n",gMajor);
	}

	PK("Request IRQs for PWM_INT.\n");
	result = request_irq(AITC_PWM_INT,
 			pwm_interrupt,
			SA_INTERRUPT,
			DEV_IRQ_NAME,
			DEV_IRQ_ID);
	if (result)
	{
		PK("<1>cannot init major= %d irq=%d\n", gMajor, irq);

		devfs_unregister_chrdev(gMajor, MOD_NAME);
		devfs_unregister(devfs_handle);			
		return -1;
	}

	// init wait queue
	init_waitqueue_head(&ts_wait);

	// register power manager
	pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, handle_pm_event);

	// init
	initpwm();

	PK("<1>Init module Complete\n");
	return 0;
}


/******************************************************************************
 * Function Name: pwm_cleanup
 *
 * Input: 		void	:
 * Value Returned:	void	:
 *
 * Description: clean up and free all of resource for this MODULE
 *
 * Modification History:
 * 	10 DEC,2001, 
 *****************************************************************************/
#ifdef MODULE
void cleanup_module(void)
#else
void __exit pwm_cleanup(void)
#endif
{

	free_irq(AITC_PWM_INT, DEV_IRQ_ID);


	devfs_unregister_chrdev(gMajor, MOD_NAME);
	devfs_unregister(devfs_handle);	

	disable_irq(AITC_PWM_INT);
}

// --------------------------------------------------------------------
// local rutines

/******************************************************************************
 * Function Name: checkDevice
 *
 * Input: 		inode	:
 * Value Returned:	int	: Return status.If no error, return 0.
 *
 * Description: verify if the inode is a correct inode
 *
 * Modification History:
 * 	10 DEC,2001, 
 *****************************************************************************/
static int checkDevice(struct inode *pInode)
{
	int minor;
	kdev_t dev = pInode->i_rdev;

	if( MAJOR(dev) != gMajor)
	{
		PK("<1>checkDevice bad major = %d\n",MAJOR(dev) );
		return -1;
	}
	minor = MINOR(dev);

	if ( minor < MAX_ID )
		return minor;
	else
	{
		PK("<1>checkDevice bad minor = %d\n",minor );
		return -1;
	}
}

/* timer */
int CreateTimer(PWM_Timer_t *timer)
{
	init_timer(timer->timer_blk_ptr);
	timer->timer_blk_ptr->function = timer->timer_func;

	return(0);
}

int StartTimer(PWM_Timer_t *timer)
{

	timer->timer_blk_ptr->expires = jiffies + timer->period;
	timer->stop_flag = 0;

	add_timer((struct timer_list *)timer->timer_blk_ptr);

	return(0);

}
int StopTimer(PWM_Timer_t *timer)
{

	timer->stop_flag = 1;
	del_timer_sync((struct timer_list *)timer->timer_blk_ptr);

	return(0);
}

void pwmIntFunc()
{
U32	period;

	PK("<1>pwm sam int\n");

	if (gWriteCnt > 0)
	{
		PK("<1>PWMS = 0x%4x\n", (U16)_reg_PWM_PWMS);

		// 96M/128/2/period
		period = *gpWriteBufPtr16++;

		if(period > 0)
//			_reg_PWM_PWMP = 96000000/128/12/2/period; //96000000/128/2*11
			_reg_PWM_PWMP = 66000000/128/2/period; //96000000/128/2*11
		PK("<1>PWMP = 0x%4x\n", (U16)_reg_PWM_PWMP);
		PK("<1>PWMCNT = 0x%4x\n", (U16)_reg_PWM_PWMCNT);

		StartTimer(&pwmTimer);

		gWriteCnt--;
	}
	else
		StopPwm();

}

void StopPwm()
{
	if(gpWriteBuf)
		kfree(gpWriteBuf);

	_reg_PWM_PWMC &= ~0x00000040;	// disable IRQEN
	_reg_PWM_PWMC &= ~0x00000010;	// disable EN

	gWriteOk = 1;
	gWriteCnt = 0;
	gDataLen = 0;
	gSampleValue = 0;

	if(gPwmMode == PWM_TONE_MODE)
		StopTimer(&pwmTimer);

	// can release PWM now
	wake_up_interruptible(&ts_wait);

	PK("<1>data completed.\n");
	PK("<1>PWMC = 0x%8x\n", (U32)_reg_PWM_PWMC);
}

static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data)
{
	switch(rqst)
	{
		case PM_SUSPEND:
			PK("<1> PM suspend event received in PWM device.\n");
			StopPwm();

			break;
		case PM_RESUME:
			PK("<1> PM resume event received in PWM device.\n");
			break;
		default:
			break;
	}
    return 0;
} /* handle_pm_event */


#ifndef MODULE
module_init(pwm_init);
module_exit(pwm_cleanup);
#endif

/* end of file */

⌨️ 快捷键说明

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