# 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; } ```