一、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. random——伪随机数生成模块

    random——伪随机数生成模块 转自:https://blog.csdn.net/zhtysw/article/details/79978197 该模块包含构造伪随机数生成器的多个方法.对于整数,伪 ...

  2. DHCP原理

    一台主机的ip地址可用通过两种方式来设置.1 手动输入:2 自动向DHCP服务器获取.手动输入会出现错误,比如输入一个已经分配的ip地址,当内网机器只有几台,十几台还可以忍受,如果是几百台呢,不可能一 ...

  3. day22—一个AngularJS框架应用toDoList

    转行学开发,代码100天——2018-04-07 今天用AngularJS照着课程写了一个案例,即toDoList,记事清单效果. 主要实现以下效果: 1.通过文本框添加内容,同时添加事件列表.主要用 ...

  4. Island Transport 【HDU - 4280】【最大流Dinic】

    题目链接 可以说是真的把时间卡爆了,不断的修改了好多次之后才A了,一直T一直T,哭了…… 可以说是很练时间优化了,不断的改,不断的提交,最后竟然是改了Dinic中的BFS()中,我们一旦搜索到了T之后 ...

  5. 机器学习 coursera_ML

    在开始看之前,浏览器一直出现缓冲问题,是配置文件设置的不对,最后搞定,高兴!解决方法如下: 1.到C:\Windows\System32\drivers\etc下找到host文件,并以文本方式打开, ...

  6. [Linux] 005 Linux 常见目录的作用及一些注意事项

    1. Linux 常见目录及其作用 目录名 作用 /bin/ 存放系统命令的目录普通用户各超级用户都可以执行放在 /bin 下的命令在单用户模式下也可以执行 /sbin/ 保存和系统环境相关的命令只有 ...

  7. hdu4352 XHXJ's LIS(数位dp)

    题目传送门 XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  8. CentOS7安装MySQL5.7.20

    参考1:https://www.cnblogs.com/technology-huangyan/p/10484838.html 参考1:https://blog.csdn.net/aiyowei110 ...

  9. IEnumerable和IEnumerator 详解 分类: C# 2014-12-05 11:47 18人阅读 评论(0) 收藏

    原:<div class="article_title"> <span class="ico ico_type_Original">&l ...

  10. 实现combobox模糊查询的时候报错 InvalidArgument=“0”的值对于“index”无效

    因为要对combobox实现模糊查询,因为系统实现的匹配只能从左到右进行匹配,所以利用两个list来进行模糊匹配,主要代码如下: List<string> listOnit = new L ...