一、4412 xpwmTOUT1

这是4412的GPD0_1路,itop中被使用为LCD的背光电路的pwm功能。因此如果使用教程中的代码,同样操作GPD0_1是行不通的。

会出现错误,所以需要解除在内核中的占用

修改arch/arm/mach-exynos/mach-itop4412.c,找到并注释

    samsung_bl_set(&smdk4x12_bl_gpio_info, &smdk4x12_bl_data);

在内核中取消相关的模块编译,(不确定)

Device Driver>>Graphics support>>Backlight & LCD device support(取消)

然后在平台文件中增加注册设备:

    &s3c_device_timer[],

然后是测试代码:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/backlight.h>
#include <linux/err.h>
#include <linux/pwm.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>
#include <linux/ioctl.h>
#include <asm-generic/uaccess.h> #define DEVICE_NAME "my_pwm3_dev"
#define DRIVER_NAME "my_pwm3_drv" #define PWM_MAGIC 'p'
#define PWM_MAX_NR 3 #define PWM_IOCTL_STOP _IO(PWM_MAGIC, 0)
#define PWM_IOCTL_SET_FREQ _IO(PWM_MAGIC, 1)
#define PWM_IOCTL_SET_DUTY _IO(PWM_MAGIC, 2) #define NS_IN_1HZ (1000000000UL) #define BUZZER_PWM_ID 0
#define PWM1_ID 1
#define PWM2_ID 2
#define PWM3_ID 3 #define BUZZER_PMW_GPIO EXYNOS4_GPD0(0)
#define PWM1_GPIO EXYNOS4_GPD0(1)
#define PWM2_GPIO EXYNOS4_GPD0(2)
#define PWM3_GPIO EXYNOS4_GPD0(3) static struct pwm_device *pwm4buzzer;
static struct semaphore lock;
static int period_ns = ;
static unsigned long freq = ;
static unsigned long duty = ; static void pwm_set_freq(void)
{
//配置周期
period_ns = NS_IN_1HZ / freq;
//配置占空比
if(duty < )
duty = ;
pwm_disable(pwm4buzzer);
pwm_config(pwm4buzzer, period_ns / duty, period_ns);
pwm_enable(pwm4buzzer);
//配置相应的GPIO,蜂鸣器IO配置成PWM输出模式
s3c_gpio_cfgpin(PWM3_GPIO, S3C_GPIO_SFN());
} static void pwm_stop(void)
{
s3c_gpio_cfgpin(PWM3_GPIO, S3C_GPIO_OUTPUT); pwm_config(pwm4buzzer, , NS_IN_1HZ / );
pwm_disable(pwm4buzzer);
} static int ops_pwm_open(struct inode *inode, struct file *file)
{
if(!down_trylock(&lock))
return ;
else
return -EBUSY;
} static int ops_pwm_close(struct inode *inode, struct file *file)
{
up(&lock);
return ;
} static long ops_pwm_ioctl(struct file *filep, unsigned int cmd,
unsigned long arg)
{
if(_IOC_TYPE(cmd)!=PWM_MAGIC) return -EINVAL;
if(_IOC_NR(cmd) > PWM_MAX_NR) return -EINVAL; switch(cmd) {
case PWM_IOCTL_SET_FREQ:
if(arg == )
return -EINVAL;
get_user(freq, (unsigned long __user *)arg);
printk(KERN_EMERG "freq is %ld\n", freq);
pwm_set_freq();
break;
case PWM_IOCTL_STOP:
pwm_stop();
break;
case PWM_IOCTL_SET_DUTY:
get_user(duty, (unsigned long __user *)arg);
printk(KERN_EMERG "duty is %ld\n", duty);
pwm_set_freq();
break;
default:
pwm_stop();
break;
}
return ;
} static struct file_operations pwm_ops = {
.owner = THIS_MODULE,
.open = ops_pwm_open,
.release = ops_pwm_close,
.unlocked_ioctl = ops_pwm_ioctl,
}; static struct miscdevice pwm_misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &pwm_ops,
}; static int __init iTop4412_pwm_dev_init(void)
{
int ret;
gpio_free(PWM3_GPIO); ret = gpio_request(PWM3_GPIO, DEVICE_NAME);
if(ret) {
printk(KERN_EMERG "request GPIO %d for pwm failed\n", PWM3_GPIO);
return ret;
} gpio_set_value(PWM3_GPIO, );
s3c_gpio_cfgpin(PWM3_GPIO, S3C_GPIO_OUTPUT); pwm4buzzer = pwm_request(PWM3_ID, DEVICE_NAME);
if (IS_ERR(pwm4buzzer)) {
printk(KERN_EMERG "request pwm %d for %s failed\n", PWM3_ID, DEVICE_NAME);
return -ENODEV;
}
pwm_stop(); sema_init(&lock, );
ret = misc_register(&pwm_misc_dev);
if(ret < ) {
gpio_free(BUZZER_PMW_GPIO);
pwm_free(pwm4buzzer);
misc_deregister(&pwm_misc_dev);
} printk(KERN_EMERG "\tinitialized\n"); return ret;
} static void __exit iTop4412_pwm_dev_exit(void)
{
gpio_free(BUZZER_PMW_GPIO);
pwm_free(pwm4buzzer);
misc_deregister(&pwm_misc_dev); printk(KERN_EMERG "\texit\n");
return;
} module_init(iTop4412_pwm_dev_init);
module_exit(iTop4412_pwm_dev_exit); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chen Tuo");
MODULE_DESCRIPTION("Exynos4 PWM Driver");

my_pwm3.c

然后是应用程序:

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/ioctl.h> #define PWM2_NAME "/dev/my_pwm3_dev" #define PWM_MAGIC 'p'
#define PWM_MAX_NR 3 #define PWM_IOCTL_STOP _IO(PWM_MAGIC, 0)
#define PWM_IOCTL_SET_FREQ _IO(PWM_MAGIC, 1)
#define PWM_IOCTL_SET_DUTY _IO(PWM_MAGIC, 2) int fd = -; void open_pwm1(void);
void close_pwm1(void);
void set_pwm_freq(int freq);
void set_pwm_duty(int duty);
void stop_pwm(void); void open_pwm1(void)
{
fd = open(PWM2_NAME, O_RDWR);
if(fd < ) {
perror("open pwm1 device");
exit();
} // atexit(close_pwm1);
} void close_pwm1(void)
{
if(fd >= ) {
ioctl(fd, PWM_IOCTL_STOP);
close(fd);
fd = -;
}
} void set_pwm_freq(int freq)
{
int ret = ioctl(fd, PWM_IOCTL_SET_FREQ, &freq);
if(ret < ) {
perror("set the frequency of the buzzer");
exit();
}
} void set_pwm_duty(int duty)
{
int ret = ioctl(fd, PWM_IOCTL_SET_DUTY, &duty);
if(ret < ) {
perror("set the duty of the pwm");
exit();
}
} void stop_pwm(void)
{
int ret = ioctl(fd, PWM_IOCTL_STOP);
if(ret < ) {
perror("Stop the buzzer");
exit();
}
} int main(int argc, char *argv[])
{
int freq = ; open_pwm1();
stop_pwm();
if(argc < ) {
printf("usage:%s [cmd] [arg]\n", argv[]);
printf("\tstop:%s [0] [0] \n",argv[]);
printf("\tset freq:%s [1] [arg]\n", argv[]);
printf("\tset duty:%s [2] [arg]\n", argv[]);
}
switch(atoi(argv[]))
{
case :
set_pwm_duty(atoi(argv[]));
break;
case :
set_pwm_freq(atoi(argv[]));
break;
case :
default:
stop_pwm();
return -;
} return ;
}

my_pwm3_app.c

最后是Makefile:

TARGET_NAME = my_pwm3
#TARGET_NAME = example_pwm
APP1_NAME = my_pwm3_app
#APP2_NAME = open_atomic_int_two
obj-m += $(TARGET_NAME).o KDIR := /home/topeet/chen/kernel-3.0/iTop4412_Kernel_3. PWD ?= $(shell pwd) all:app1
make -C $(KDIR) M=$(PWD) modules
app1:
arm-none-linux-gnueabi-gcc $(APP1_NAME).c -o $(APP1_NAME) -static
#app2:
# arm-none-linux-gnueabi-gcc $(APP2_NAME).c -o $(APP2_NAME) -static clean:
rm -rf *.o *.ko *.mod.c *.symvers *.order \
.$(TARGET_NAME)* $(APP1_NAME) $(APP2_NAME)

Makefile

二、4412 I2C_SDA7和I2C_SCL7

注释平台文件中的代码:

//  s3c_i2c7_set_platdata(NULL);
// i2c_register_board_info(7, i2c_devs7, ARRAY_SIZE(i2c_devs7));

和这个

//  &s3c_device_i2c7,

然后make menuconfig

>>Device Drivers>>Input device support>>Touchscreens【】取消选择

三、尝试编写控制PWM波形的驱动和应用程序

my_pwm3.c(驱动)

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/backlight.h>
#include <linux/err.h>
#include <linux/pwm.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>
#include <linux/ioctl.h>
#include <asm-generic/uaccess.h> #define DEVICE_NAME "my_pwm3_dev"
#define DRIVER_NAME "my_pwm3_drv" #define PWM_MAGIC 'p'
#define PWM_MAX_NR 3 #define PWM_IOCTL_STOP _IO(PWM_MAGIC, 0)
#define PWM_IOCTL_SET_FREQ _IO(PWM_MAGIC, 1)
#define PWM_IOCTL_SET_DUTY _IO(PWM_MAGIC, 2) #define NS_IN_1HZ (1000000000UL) #define BUZZER_PWM_ID 0
#define PWM1_ID 1
#define PWM2_ID 2
#define PWM3_ID 3 #define BUZZER_PMW_GPIO EXYNOS4_GPD0(0)
#define PWM1_GPIO EXYNOS4_GPD0(1)
#define PWM2_GPIO EXYNOS4_GPD0(2)
#define PWM3_GPIO EXYNOS4_GPD0(3) static struct pwm_device *pwm4buzzer;
static struct semaphore lock;
static int period_ns = ;
static unsigned long freq = ;
static unsigned long duty = ; static void pwm_set_freq(void)
{
//配置周期
period_ns = NS_IN_1HZ / freq;
//配置占空比
if(duty < )
duty = ;
pwm_disable(pwm4buzzer);
pwm_config(pwm4buzzer, period_ns / duty, period_ns);
pwm_enable(pwm4buzzer);
//配置相应的GPIO,蜂鸣器IO配置成PWM输出模式
s3c_gpio_cfgpin(PWM3_GPIO, S3C_GPIO_SFN());
} static void pwm_stop(void)
{
s3c_gpio_cfgpin(PWM3_GPIO, S3C_GPIO_OUTPUT); pwm_config(pwm4buzzer, , NS_IN_1HZ / );
pwm_disable(pwm4buzzer);
} static int ops_pwm_open(struct inode *inode, struct file *file)
{
if(!down_trylock(&lock))
return ;
else
return -EBUSY;
} static int ops_pwm_close(struct inode *inode, struct file *file)
{
up(&lock);
return ;
} static long ops_pwm_ioctl(struct file *filep, unsigned int cmd,
unsigned long arg)
{
if(_IOC_TYPE(cmd)!=PWM_MAGIC) return -EINVAL;
if(_IOC_NR(cmd) > PWM_MAX_NR) return -EINVAL; switch(cmd) {
case PWM_IOCTL_SET_FREQ:
if(arg == )
return -EINVAL;
get_user(freq, (unsigned long __user *)arg);
printk(KERN_EMERG "freq is %ld\n", freq);
pwm_set_freq();
break;
case PWM_IOCTL_STOP:
pwm_stop();
break;
case PWM_IOCTL_SET_DUTY:
get_user(duty, (unsigned long __user *)arg);
printk(KERN_EMERG "duty is %ld\n", duty);
pwm_set_freq();
break;
default:
pwm_stop();
break;
}
return ;
} static struct file_operations pwm_ops = {
.owner = THIS_MODULE,
.open = ops_pwm_open,
.release = ops_pwm_close,
.unlocked_ioctl = ops_pwm_ioctl,
}; static struct miscdevice pwm_misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &pwm_ops,
}; static int __init iTop4412_pwm_dev_init(void)
{
int ret;
gpio_free(PWM3_GPIO); ret = gpio_request(PWM3_GPIO, DEVICE_NAME);
if(ret) {
printk(KERN_EMERG "request GPIO %d for pwm failed\n", PWM3_GPIO);
return ret;
} gpio_set_value(PWM3_GPIO, );
s3c_gpio_cfgpin(PWM3_GPIO, S3C_GPIO_OUTPUT); pwm4buzzer = pwm_request(PWM3_ID, DEVICE_NAME);
if (IS_ERR(pwm4buzzer)) {
printk(KERN_EMERG "request pwm %d for %s failed\n", PWM3_ID, DEVICE_NAME);
return -ENODEV;
}
pwm_stop(); sema_init(&lock, );
ret = misc_register(&pwm_misc_dev);
if(ret < ) {
gpio_free(BUZZER_PMW_GPIO);
pwm_free(pwm4buzzer);
misc_deregister(&pwm_misc_dev);
} printk(KERN_EMERG "\tinitialized\n"); return ret;
} static void __exit iTop4412_pwm_dev_exit(void)
{
gpio_free(BUZZER_PMW_GPIO);
pwm_free(pwm4buzzer);
misc_deregister(&pwm_misc_dev); printk(KERN_EMERG "\texit\n");
return;
} module_init(iTop4412_pwm_dev_init);
module_exit(iTop4412_pwm_dev_exit); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chen Tuo");
MODULE_DESCRIPTION("Exynos4 PWM Driver");

my_pwm3.c

my_pwm3_app.c

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/ioctl.h> #define PWM2_NAME "/dev/my_pwm3_dev" #define PWM_MAGIC 'p'
#define PWM_MAX_NR 3 #define PWM_IOCTL_STOP _IO(PWM_MAGIC, 0)
#define PWM_IOCTL_SET_FREQ _IO(PWM_MAGIC, 1)
#define PWM_IOCTL_SET_DUTY _IO(PWM_MAGIC, 2) int fd = -; void open_pwm1(void);
void close_pwm1(void);
void set_pwm_freq(int freq);
void set_pwm_duty(int duty);
void stop_pwm(void); void open_pwm1(void)
{
fd = open(PWM2_NAME, O_RDWR);
if(fd < ) {
perror("open pwm1 device");
exit();
} // atexit(close_pwm1);
} void close_pwm1(void)
{
if(fd >= ) {
ioctl(fd, PWM_IOCTL_STOP);
close(fd);
fd = -;
}
} void set_pwm_freq(int freq)
{
int ret = ioctl(fd, PWM_IOCTL_SET_FREQ, &freq);
if(ret < ) {
perror("set the frequency of the buzzer");
exit();
}
} void set_pwm_duty(int duty)
{
int ret = ioctl(fd, PWM_IOCTL_SET_DUTY, &duty);
if(ret < ) {
perror("set the duty of the pwm");
exit();
}
} void stop_pwm(void)
{
int ret = ioctl(fd, PWM_IOCTL_STOP);
if(ret < ) {
perror("Stop the buzzer");
exit();
}
} int main(int argc, char *argv[])
{
int freq = ; open_pwm1();
stop_pwm();
if(argc < ) {
printf("usage:%s [cmd] [arg]\n", argv[]);
printf("\tstop:%s [0] [0] \n",argv[]);
printf("\tset freq:%s [1] [arg]\n", argv[]);
printf("\tset duty:%s [2] [arg]\n", argv[]);
}
switch(atoi(argv[]))
{
case :
set_pwm_duty(atoi(argv[]));
break;
case :
set_pwm_freq(atoi(argv[]));
break;
case :
default:
stop_pwm();
return -;
} return ;
}

my_pwm3_app.c

Makefile

TARGET_NAME = my_pwm3
#TARGET_NAME = example_pwm
APP1_NAME = my_pwm3_app
#APP2_NAME = open_atomic_int_two
obj-m += $(TARGET_NAME).o KDIR := /home/topeet/chen/kernel-3.0/iTop4412_Kernel_3. PWD ?= $(shell pwd) all:app1
make -C $(KDIR) M=$(PWD) modules
app1:
arm-none-linux-gnueabi-gcc $(APP1_NAME).c -o $(APP1_NAME) -static
#app2:
# arm-none-linux-gnueabi-gcc $(APP2_NAME).c -o $(APP2_NAME) -static clean:
rm -rf *.o *.ko *.mod.c *.symvers *.order \
.$(TARGET_NAME)* $(APP1_NAME) $(APP2_NAME)

Makfile

总结:内核接收ioctl的信息时需要使用特定的函数进行保护,防止被乱七八糟的传入数据。

4412 4路pwm输出的更多相关文章

  1. 16路PWM输出的pca9685模块

    今天要介绍的就是该模块,该模块是16路pwm模块,使用I2C总线可以控制16路舵机(led). 接线OE空着就可以,其他VCC是芯片供电+5,SCL时钟线,SDA信号线,GND地线. 芯片介绍可以看: ...

  2. J20航模遥控器开源项目系列教程(五)| 制作STM32F0接收机,8路PWM输出,SBUS输出,PPM输出 | 加密狗无线化,畅玩飞行模拟器

    我们的开源宗旨:自由 协调 开放 合作 共享 拥抱开源,丰富国内开源生态,开展多人运动,欢迎加入我们哈~ 和一群志同道合的人,做自己所热爱的事! 项目开源地址:https://github.com/J ...

  3. STM32 PWM输出(映射)

    STM32 的定时器除了 TIM6 和 7.其他的定时器都可以用来产生 PWM 输出.其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出.而通用定时器也能同时产生多达 4 ...

  4. 定时器同步+触发三ADC采样+输出6路PWM波

    为了熟悉定时器定时器和ADC 用STM32F407DIS做了一个简单的工程: 通过高级定时器TIM1溢出更新时间作为触发输出信号(TRGO),触发TIM8开始计数: 同时TIM1的通道1.2.3以及分 ...

  5. (五)转载:通用定时器PWM输出

    1.     TIMER输出PWM基本概念 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有 ...

  6. STM32 HAL库学习系列第4篇 定时器TIM----- 开始定时器与PWM输出配置

    基本流程: 1.配置定时器 2.开启定时器 3.动态改变pwm输出,改变值  HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1); 函数总结: __HAL_TIM ...

  7. STM32(7)——通用定时器PWM输出

    1.TIMER输出PWM基本概念         脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种 ...

  8. stm32 PWM输出学习

    STM32 的定时器除了 TIM6 和 7,其他的定时器都可以用来产生 PWM 输出.其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出.通用定时器也能同时产生多达 4路 ...

  9. STM32F103ZET6 PWM输出

    1.通用定时器的PWM功能 STM32F103ZET6有4个通用定时器,分别是TIM2.TIM3.TIM4.TIM5. 通用定时器由一个可编程预分频器驱动的16位自动装载计数器构成. 通用定时器的很多 ...

随机推荐

  1. 【CDN+】 一些常用的Linux命令,crontab+VI+Hive(持续更新)

    前言 本文主要是记录下工作中可能用到的一些linux指令,当作字典查用 Crontab 基本命令 # 安装 yum -y install vixie-cron crontabs#查看状态 servic ...

  2. Nginx 配置 location 以及 return、rewrite 和 try_files 指令

    正则表达式 Nginx 内置的全局变量 location 前缀字符串及优先级 示例 location 匹配原则 if 和 break 指令 if break return.rewrite 和 try_ ...

  3. org.dom4j 解析XML

    org.dom4j 解析xml java 代码 1 import java.io.File; import java.io.FileOutputStream; import java.io.FileW ...

  4. Vue过渡:JavaScript钩子

    一 App.vue <template> <div id="app"> <button @click="show = !show" ...

  5. 网络流强化-HDU2732

    第一次遇到加了“多余”的边会导致WA的——在我看来是很多余,见代码191行 之后会思考为什么,想出来再更. 问题弄明白了,如果你在连接边连了一条到没有柱子的点的边,这个没有柱子的点是不可能连到终点的, ...

  6. Play with Chain 【HDU - 3487】【Splay+TLE讲解】

    题目链接 很好的一道题,用了三天多的时间,终于知道了我为什么T的原因,也知道了在Splay的同时该怎样子的节约时间,因为Splay本身就是大常数的O(N*logN),我们如果不在各种细节上节约时间,很 ...

  7. ToString()的简单介绍

    1.在某一个类中重写该类的toString()方法,是为了方便打印该类实例中的内容.

  8. JS原型链详解

    最近面试被问到了就决定好好深入理解原型链 对象 要清楚原型链,首先要弄清楚对象: 普通对象 最普通的对象:有__proto__属性(指向其原型链),没有prototype属性. 原型对象(person ...

  9. 【洛谷p1025】数的划分

    数的划分[传送门] 算法的话,dfs+剪枝: 据说是01年之前的NOIp提高组: 思路: 这道题是求把n无序的划分成k份的方案数,最直接的搜索方法是依次枚举x1,x2……xk的值,然后判断,显然这么搜 ...

  10. 利用java反射动态调用方法,生成grid数据

    项目中需要java后台查询并组装前台grid的数据,数据行数不定,数据行定义不定,开始用了最原始的方法,写了几百行,就是前台需要什么字段后台拼接什么字段,java代码冗余量非常大,并且不够灵活,一旦前 ...