# 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",°ree);
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;
}
```