| 
 
初级会员 
 
	积分68金钱68 注册时间2020-5-19在线时间14 小时 | 
 
 发表于 2021-5-17 16:42:45
|
显示全部楼层 
| 我也发现这个问题,我刚刚解决了。 正点原子和野火对于这个pwm,都没有说清楚。
 韦东山老师没有pwm的讲解。
 我结合他们三位老师的讲解,我摸索着解决了问题:
 我这是实现了两路pwm的驱动和app测试
 设备树:
 
 复制代码
        fs_pwm {
                compatible = "fsml,fs_pwm";
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_fspwm>;
                pwm_power {
                        pwm-names = "pwm_power";
                        pwms =         <&pwm1 0 50000>;
                };
                pwm_motor {
                        pwm-names = "pwm_motor";
                        pwms =         <&pwm2 0 50000>;
                };
        };
        pinctrl_fspwm:fspwmgrp {
                fsl,pins = <
                        MX6UL_PAD_LCD_DATA00__PWM1_OUT          0x1b0b0        /*/pwm1&motor pwm*/        
                        MX6UL_PAD_LCD_DATA01__PWM2_OUT          0x1b0b0        /*/pwm1&motor pwm*/        
                >;
驱动:
 
 复制代码#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/err.h>
#include <linux/pwm.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
struct pwm_device        *pwm_power_dev = NULL;  //定义pwm设备结构体
struct pwm_device   *pwm_motor_dev = NULL;
/*精简版 prob函数*/
/* 1. 确定主设备号                                                                 */
static int major = 0;
static struct class *fspwm_class;
//static struct gpio_desc *led_gpio;
/* 3. 实现对应的open/read/write等函数,填入file_operations结构体                   */
static ssize_t fspwm_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
        printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
        return 0;
}
/* write(fd, &val, 1); */
static ssize_t fspwm_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
        int err;
    int k_buf = 0;
        short duty_ns,period;
        //struct inode *inode = file_inode(file);
        //int minor = iminor(inode);
        
        printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
        err = copy_from_user(&k_buf, (void*)buf, sizeof(int));
    period = k_buf & 0xffff;
    duty_ns = (k_buf >> 16) & 0xffff;
        err = pwm_config(pwm_power_dev, duty_ns, period);
        err = pwm_config(pwm_motor_dev, duty_ns, period);
    printk("%s %d %d %d\r\n", __FUNCTION__, k_buf,  duty_ns, period);
        
        return 1;
}
static int fspwm_open (struct inode *node, struct file *file)
{
        //int minor = iminor(node);
        
        printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
        
        return 0;
}
static int fspwm_close (struct inode *node, struct file *file)
{
        printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
        return 0;
}
/* 定义自己的file_operations结构体                                              */
static struct file_operations fspwm_dev = {
        .owner         = THIS_MODULE,
        .open    = fspwm_open,
        .read    = fspwm_read,
        .write   = fspwm_write,
        .release = fspwm_close,
};
static int pwm_power_probe_new(struct platform_device *pdev)
{
        int ret = 0;
        struct device_node * child;
        struct device_node * child2;
        struct device *dev = &pdev->dev;
        printk("match success \n");
    //注册operations
    major = register_chrdev(0, "fspwm", &fspwm_dev);
        fspwm_class = class_create(THIS_MODULE, "fspwm_class");
        if (IS_ERR(fspwm_class)) {
                printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
                unregister_chrdev(major, "fspwm");
                return PTR_ERR(fspwm_class);
        }
    device_create(fspwm_class, NULL, MKDEV(major, 0), NULL, "fspwm_%s","motor");
        child = of_get_next_child(dev->of_node, NULL);
    printk(""%s"'s child: "%s"\n", dev->of_node->full_name, child->full_name);
    printk("%s %s line %d\r\n"__FILE__, __FUNCTION__, __LINE__);
    if(NULL == child)
    {
        printk("of_get_next_child error\r\n");
    }
        if (child)
        {
                pwm_power_dev = devm_of_pwm_get(dev, child, NULL);
                if (IS_ERR(pwm_power_dev)) 
                {
                        printk(KERN_ERR" pwm_power_dev,get pwm  error!!\n");
                        return -1;
                }
        
        //pwm_motor_dev = devm_of_pwm_get(dev, chile, )
        }
        else
        {
                printk(KERN_ERR" pwm_power_dev of_get_next_child  error!!\n");
                return -1;
        }
        child2 = of_get_next_child(dev->of_node, child);
    
    printk(""%s"'s child2: "%s"\n", dev->of_node->full_name, child2->full_name);
    printk(""%s"'s child2: "%s"\n", dev->of_node->full_name, child2->full_name);
    printk(""%s"'s child2: "%s"\n", dev->of_node->full_name, child2->full_name);
    printk("%s %s line %d\r\n"__FILE__, __FUNCTION__, __LINE__);
    if(NULL == child2)
    {
        printk("of_get_next_child2 error\r\n");
    }
        if (child2)
        {
        if (IS_ERR(child2)) 
                {
                        printk(KERN_ERR" of_get_next_child,child2  error!!\n");
                        return -1;
                }
        printk(""%s"'s devm_of_pwm_get: "%s"\n", dev->of_node->full_name, child2->full_name);
                pwm_motor_dev = devm_of_pwm_get(dev, child2, NULL);
        //pwm_motor_dev = devm_pwm_get(dev, child2->full_name);
                if (IS_ERR(pwm_motor_dev)) 
                {
                        printk(KERN_ERR" pwm_power_dev,get pwm  error!!\n");
                        return -1;
                }
        }
        else
        {
                printk(KERN_ERR" pwm_power_dev of_get_next_child  error!!\n");
                return -1;
        }
    printk("set pwm_power...\r\n");
        /*配置频率100KHz 占空比80%*/
        ret = pwm_config(pwm_power_dev, 1000, 5000);
    printk("ret:%d\r\n", ret);
        /*反相 频率100KHz 占空比20%*/
        ret = pwm_set_polarity(pwm_power_dev, PWM_POLARITY_INVERSED);
    printk("ret:%d\r\n", ret);
        ret = pwm_enable(pwm_power_dev);
    printk("ret:%d\r\n", ret);
    printk("set pwm_motor...\r\n");
        /*配置频率100KHz 占空比80%*/
        ret = pwm_config(pwm_motor_dev, 1000, 5000);
    printk("ret:%d\r\n", ret);
        /*反相 频率100KHz 占空比20%*/
        ret = pwm_set_polarity(pwm_motor_dev, PWM_POLARITY_NORMAL);
    printk("ret:%d\r\n", ret);
        ret = pwm_enable(pwm_motor_dev);
    printk("ret:%d\r\n", ret);
        return ret;
}
static int pwm_power_remove(struct platform_device *pdev)
{
        device_destroy(fspwm_class, MKDEV(major, 0));
        class_destroy(fspwm_class);
        unregister_chrdev(major, "fspwm");
    printk("%s %s line %d\r\n"__FILE__, __FUNCTION__, __LINE__);
        return 0;
}
static const struct of_device_id of_pwm_leds_match[] = {
        {.compatible = "fs_pwm"},
        {},
};
static struct platform_driver led_pwm_driver = {
        .probe                = pwm_power_probe_new,
        .remove                = pwm_power_remove,
        .driver                = {
                .name        = "fs_pwm",
                .of_match_table = of_pwm_leds_match,
        },
};
/*
*驱动初始化函数
*/
static int __init pwm_driver_init(void)
{
    printk("%s %s line %d\r\n"__FILE__, __FUNCTION__, __LINE__);
        return platform_driver_register(&led_pwm_driver);
}
/*
*驱动注销函数
*/
static void __exit pwm_driver_exit(void)
{
        printk(KERN_ERR "%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
        /*注销平台设备*/
        platform_driver_unregister(&led_pwm_driver);
}
module_init(pwm_driver_init);
module_exit(pwm_driver_exit);
MODULE_LICENSE("GPL");
 
 APP:
 
 复制代码#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
//#include "linux/ioctl.h"
#include "sys/ioctl.h"
int main(int argc, char *argv[])
{
    int fd = 0;
    int ret = 0;
    int data = 0;
    char *filename = NULL;
    unsigned int value = 0;
    unsigned short duty,period;
    int cmd=0;
    printf("\r\n\r\n\r\nargc num:%d\r\n",argc);
    filename = argv[1];
    duty = atoi(argv[2]);
    period = atoi(argv[3]);
    cmd = (duty << 16)+period;
    fd = open(filename, O_RDWR);
    if(0 > fd)
    {
        printf("can't open file %s\r\n", filename);
        return -1;
    }
    printf("open fsio_dev ok cmd:%d\r\n",cmd);
    write(fd, &cmd, sizeof(int));
    close(fd);
    printf("open fsio_dev ok cmd:%d,%d,%d\r\n",cmd,duty,period);
    return ret;    
}
 | 
 |