Duo256 UART0_RX引脚复用

将UART0_RX转为GPIO或PWM,发现通过*vir_gpioA17_dr&=~(1<<17);无法控制GPIO,但通过终端使用echo命令却可以控制GPIO的电平,我不清楚是哪里出了问题 :sob:。我用类似的方法可以控制GPIOA14 。



//pwm_kernel.c

#include "linux/init.h"
#include "linux/module.h"
#include "linux/miscdevice.h"
#include "linux/fs.h"
#include "linux/uaccess.h"
#include "linux/io.h"

#define FMUX_GPIO_REG_IOCTRL_UART0_RX 0x03001044
#define GPIOA_DDR (0x03020000+0x000)
#define GPIOA_DR  (0x03020000+0x004)
unsigned int *vir_mux;
unsigned int *vir_gpioA17_ddr;
unsigned int *vir_gpioA17_dr;

ssize_t pwm_read(struct file *file, char __user *user_buf, size_t size, loff_t * loff){
    return 0;
}

ssize_t pwm_write(struct file *file, const char __user *user_buf, size_t size, loff_t * loff){
    char kernel_buf[64]={0};
    printk("led_write\n");
    if(copy_from_user(kernel_buf,user_buf,size)!=0) {
        printk("copy_from_user error\n");
        return -1;
    }else {
        if (kernel_buf[0]=='1') {
            *vir_gpioA17_dr|=(1<<17);
        }else if(kernel_buf[0]=='0') {
            *vir_gpioA17_dr&=~(1<<17);
        }
        return 0;
    }
}

int pwm_open(struct inode *inode, struct file *file){
    return 0;
}

int pwm_release(struct inode *inode, struct file *file){
    return 0;
}


struct file_operations pwm_fops={
    .owner=THIS_MODULE,
    .write=pwm_write,
    .read=pwm_read,
    .open=pwm_open,
    .release=pwm_release
};

static struct miscdevice pwm_dev={
        .minor=MISC_DYNAMIC_MINOR,
        .fops=&pwm_fops,
        .name="pwm_led_dev"
};

static int __init pwm_init(void){
    printk("pwm_init\n");
    if(misc_register(&pwm_dev)<0){
        printk("misc_register error\n");
        return -1;
    } else{
        printk("misc_register succeed\n");
        vir_mux=ioremap(FMUX_GPIO_REG_IOCTRL_UART0_RX,4);
        vir_gpioA17_ddr=ioremap(GPIOA_DDR,4);
        vir_gpioA17_dr=ioremap(GPIOA_DR,4);
        if(vir_mux==NULL||vir_gpioA17_ddr==NULL||vir_gpioA17_dr==NULL){
            printk("ioremap error\n");
            return -1;
        } else{
            printk("ioremap succeed\n");
        }
        writel(3,vir_mux);
        *vir_gpioA17_ddr|=(1<<17);
        *vir_gpioA17_dr&=~(1<<17);
        return 0;
    }
}

static void __exit pwm_exit(void){
    printk("pwm_exit\n");
    misc_deregister(&pwm_dev);
    iounmap(vir_mux);
    iounmap(vir_gpioA17_ddr);
    iounmap(vir_gpioA17_dr);
}

MODULE_LICENSE("GPL");
module_init(pwm_init);
module_exit(pwm_exit);
#include "stdio.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc,char *argv[]){
    int fd= open("/dev/pwm_led_dev",O_RDWR);
    if(fd<0){
        perror("open error");
        return -1;
    } else{
        write(fd,argv[1],sizeof(argv[1]));
        close(fd);

        return 0;
    }
}

引脚复用可以参看这里Pwm的使用与设备树下使用gpio