---
# System prepended metadata

title: 學長的伺服馬達(使用ioctl)

---

# kernel.c
```clike=
//--t10--
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/err.h>
#include <linux/pwm.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>	
#include <linux/delay.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>

#define SERVO_MAJOR 238

#define DEVICE_NAME				"servo"

#define MAGIC_NUMBER    'L' 

#define PWM_IOCTL_SET_FREQ	_IO(MAGIC_NUMBER,  1)
#define PWM_IOCTL_STOP		_IO(MAGIC_NUMBER,  0)

#define NS_IN_1HZ			1000000000
#define PWM_IN_FREQ         NS_IN_1HZ / 50

//#define MOTOR_PWM_ID		3

#define MOTOR_PWM_GPIO	 	EXYNOS4_GPD0(3)


static long servo_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int delay1_us;
	int q;

	switch (cmd) {
		case PWM_IOCTL_SET_FREQ:
			if (arg == 0)
				return -EINVAL;
			
			printk("<1>SERVO_CTL\n");
			delay1_us = (int)arg;
			printk("cmd = %d\n freq = %d\n", cmd, delay1_us);
			
			for(q=20;q>0;q--){
			gpio_direction_output(MOTOR_PWM_GPIO, 1);
			ndelay(delay1_us);
			gpio_direction_output(MOTOR_PWM_GPIO, 0);
			ndelay(PWM_IN_FREQ - delay1_us);
			}
			break;

		case PWM_IOCTL_STOP:
		default:
			break;
	}

	return 0;

}

static int servo_open(struct inode *inode, struct file *filp)
{	/*��l�� GPIO ���}*/

	int ret1 = -1;
	int ret2 = -1;
	ret1 = gpio_request( MOTOR_PWM_GPIO, DEVICE_NAME);
	if( ret1 < 0 )	// request pin 2
	{
		printk( KERN_INFO "%s: %s unable to get TRIG gpio\n", DEVICE_NAME, __func__ );
		ret1 = -EBUSY;
		gpio_free(MOTOR_PWM_GPIO);
		return(ret1);
	}
	
	ret2 = gpio_direction_output( MOTOR_PWM_GPIO, 0);
	if( ret2 < 0 )	// Set pin 2 as output with default value 0
	{
		printk( KERN_INFO "%s: %s unable to set TRIG gpio as output\n", DEVICE_NAME, __func__ );
		ret2 = -EBUSY;
		return(ret2);
	}

	s3c_gpio_cfgpin(MOTOR_PWM_GPIO, S3C_GPIO_OUTPUT);
	
	
	return 0;
}


static int servo_release(struct inode *inode, struct file *filp)
{
	gpio_free(MOTOR_PWM_GPIO);
	return 0;
}

static struct file_operations servo_fops = 
{
	owner		    :	THIS_MODULE,
	unlocked_ioctl	:	servo_ioctl,
	open		    :	servo_open,
	release		    :	servo_release,
};

static struct class *servo_class;

static int __init servo_init(void)
{
	int retval;
	//int ret;
	
	retval = register_chrdev(SERVO_MAJOR,DEVICE_NAME,&servo_fops);
	if(retval < 0)
	{
		printk(KERN_WARNING "Can't get major %d\n",SERVO_MAJOR);
		return retval;
	}

	printk("servo driver register success!\n");
	
	servo_class = class_create(THIS_MODULE,"servo");
        if (IS_ERR(servo_class))
	{
		printk(KERN_WARNING "Can't make node %d\n",SERVO_MAJOR);
                return PTR_ERR(servo_class);
	}

    device_create(servo_class, NULL, MKDEV(SERVO_MAJOR, 0),NULL, DEVICE_NAME);
	printk("SERVO driver make node success!\n");
	
	return 0;
}
static void __exit servo_exit(void)
{
	gpio_free(MOTOR_PWM_GPIO);
    device_destroy(servo_class,MKDEV(SERVO_MAJOR, 0));
    class_destroy(servo_class);
	printk("SERVO driver remove node success!\n");
	unregister_chrdev(SERVO_MAJOR,DEVICE_NAME);
	printk("SERVO driver release success!\n");

}
module_init(servo_init);
module_exit(servo_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("michael199584566@gmail.com");
MODULE_DESCRIPTION("servo  driver");
```
# user.c
```clike=
#include <stdio.h>
#include <stdlib.h>	//system
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
//#include <linux/delay.h>
#include <sys/ioctl.h>

#define SERVO_MAJOR 238

#define DEVICE_NAME				"servo"

#define MAGIC_NUMBER    'L' 

#define PWM_IOCTL_SET_FREQ	_IO(MAGIC_NUMBER,  1)
#define PWM_IOCTL_STOP		_IO(MAGIC_NUMBER,  0)


int main(int argc, char *argv[])
{
		int i = 0;
		//int j = 0;
		int freq = 0 ;
		float duty_cycle = 0.0;
		float duty = 0.0;
		int degree = 0;
		int val = -1;
		int fd;
		int pwm_freq = 50;
		int NS_IN_1HZ = 1000000000;
		
		char *msg = "Message passed by ioctl\n", c, message[100];
		
		fd = open("/dev/servo", 0); //���豸
		if(fd<0)
		{
			perror("can not open device fileL /dev/servo\n");
			exit(-1);
		}
	
		while(1)
		{
			printf("please select number to control servo\n");
			printf("1:degree  2:for  3:exit : -> ");
			scanf("%d", &val);	
			//printf("\n");

			switch(val)
				{
				 case 1: 
					printf("1: pleae set degree \n");
					scanf("%d",&degree);
					duty_cycle = (0.05 * pwm_freq) + (0.19 * pwm_freq * degree / 180);
					duty = duty_cycle * 0.01 * (NS_IN_1HZ / pwm_freq);
					freq = (int)duty;
					printf("-----------------------------\n");
					printf("degree = %d,\nduty_cycle = %.2f,\nfreq = %d\n",degree, duty_cycle, freq);
					printf("-----------------------------\n");
					ioctl(fd, PWM_IOCTL_SET_FREQ, freq);
					//usleep(200000);					
					break;
				 case 3:
					printf("EXIT\n");
					close(fd);
					return 0;
				 case 2:
					for(i=0;i<=180;i=i+18){
					    duty_cycle = (0.05 * pwm_freq) + (0.19 * pwm_freq * i / 180);
					    duty = duty_cycle * 0.01 * (NS_IN_1HZ / pwm_freq);
					    freq = (int)duty;
						printf("-----------------------------\n");
						printf("degree = %d,\nduty_cycle = %.2f,\nfreq = %d\n", i, duty_cycle, freq);
						printf("-----------------------------\n");
					    ioctl(fd, PWM_IOCTL_SET_FREQ, freq);
					    //usleep(200000);
					}
					break;
				
				default:
					break;

			}

		}
		
		return 0;
}

```