OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3146|回复: 4

STM32MP157照着教程测试点灯发现GPIOC被莫名其妙关闭

[复制链接]

2

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2018-1-30
在线时间
10 小时
发表于 2022-3-31 15:20:37 | 显示全部楼层 |阅读模式
1金钱
使用的原子出厂的内核和文件系统
照着教程第二十一章练习点灯操作,例程编译,加载,是可以玩的,也能控制灯。
但我想着:换个IO口来玩一下,改成控制一下beep蜂鸣器的GPIOC-7的端口。
然后整个人都不好了,就是不能玩。经过各种测试,有一部分核心地方的代码如下
    /* 2、使能PI时钟 */
    val = readl(MPU_AHB4_PERIPH_LP_RCC_PI);
    val &= ~(0X1 << 2);    /* 清除以前的设置 */
    val |= (0X1 << 2);    /* 设置新值 */
    writel(val, MPU_AHB4_PERIPH_LP_RCC_PI);
   
    for(loop=0;loop<50;loop++){
        val = ioread32(MPU_AHB4_PERIPH_RCC_PI);    printk("MPU_AHB4_PERIPH_RCC_PI:%08X\r\n",val);
        
        mdelay(500);
    }
   

已经将MPU_AHB4_PERIPH_LP_RCC_PI这个虚拟地址对应的寄存器的bit3设置为1了,但是只要经过了mdelay(500)之后,回来,bit3就立马会被设置成0
有遇到过的大神,救救孩子。已经折腾了三天了,点个灯,点了三天没点亮。

(不知道从哪里上传文件,直接贴代码吧)
//=====================================================以下是代码====================================
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
/***************************************************************
Copyright &#169; ALIENTEK Co., Ltd. 1998-2029. All rights reserved.
文件名        : led.c
作者          : 正点原子
版本           : V1.0
描述           : LED驱动文件。
其他           : 无
论坛            : www.openedv.com
日志           : 初版V1.0 2020/11/23 正点原子团队创建
***************************************************************/
#define LED_MAJOR        200        /* 主设备号 */
#define LED_NAME        "led"     /* 设备名字 */

#define LEDOFF     0                /* 关灯 */
#define LEDON     1                /* 开灯 */

#define GPIO_PORT                7
#define GPIO_BASE                0xA000
#define GPIO_PIN                0


/* 寄存器物理地址 */
#define PERIPH_BASE                      (0x40000000)
#define MPU_AHB4_PERIPH_BASE            (PERIPH_BASE + 0x10000000)
#define RCC_BASE                        (MPU_AHB4_PERIPH_BASE + 0x0000)   
#define RCC_MP_AHB4ENSETR                (RCC_BASE + 0XA28)

#define RCC_MP_AHB4LPENSETR                (RCC_BASE + 0XB28)


#define GPIOI_BASE                        (MPU_AHB4_PERIPH_BASE + GPIO_BASE)   
#define GPIOI_MODER                      (GPIOI_BASE + 0x0000)   
#define GPIOI_OTYPER                      (GPIOI_BASE + 0x0004)   
#define GPIOI_OSPEEDR                      (GPIOI_BASE + 0x0008)   
#define GPIOI_PUPDR                      (GPIOI_BASE + 0x000C)   
#define GPIOI_ODR                          (GPIOI_BASE + 0x0014)   
#define GPIOI_BSRR                      (GPIOI_BASE + 0x0018)

#define GPIOC_BASE                        (MPU_AHB4_PERIPH_BASE + 0x4000)   
#define GPIOC_MODER                      (GPIOC_BASE + 0x0000)   
#define GPIOC_OTYPER                      (GPIOC_BASE + 0x0004)   
#define GPIOC_OSPEEDR                      (GPIOC_BASE + 0x0008)   
#define GPIOC_PUPDR                      (GPIOC_BASE + 0x000C)   
#define GPIOC_ODR                          (GPIOC_BASE + 0x0014)   
#define GPIOC_BSRR                      (GPIOC_BASE + 0x0018)





/* 映射后的寄存器虚拟地址指针 */
static void __iomem *MPU_AHB4_PERIPH_LP_RCC_PI;


static void __iomem *MPU_AHB4_PERIPH_RCC_PI;
static void __iomem *GPIOI_MODER_PI;
static void __iomem *GPIOI_OTYPER_PI;
static void __iomem *GPIOI_OSPEEDR_PI;
static void __iomem *GPIOI_PUPDR_PI;
static void __iomem *GPIOI_ODR_PI;
static void __iomem *GPIOI_BSRR_PI;


static void __iomem *GPIOC_MODER_PI;
static void __iomem *GPIOC_OTYPER_PI;
static void __iomem *GPIOC_OSPEEDR_PI;
static void __iomem *GPIOC_PUPDR_PI;
static void __iomem *GPIOC_ODR_PI;
static void __iomem *GPIOC_BSRR_PI;

spinlock_t lock;        /* 自旋锁 */
/*
* @description        : LED打开/关闭
* @param - sta     : LEDON(0) 打开LED,LEDOFF(1) 关闭LED
* @return             : 无
*/
void led_switch(u8 sta)
{
    u32 val = 0;
    unsigned long flags;

//    val = readl(MPU_AHB4_PERIPH_RCC_PI);
//    val &= ~(0X1 << 2);    /* 清除以前的设置 */
//    val |= (0X1 << 2);    /* 设置新值 */
//    writel(val, MPU_AHB4_PERIPH_RCC_PI);

    val = ioread32(MPU_AHB4_PERIPH_RCC_PI);    printk("MPU_AHB4_PERIPH_RCC_PI:%08X\r\n",val);
   
    val = ioread32(GPIOI_MODER_PI    );            printk("GPIOI_MODER_PI:%08X %08X\r\n",        GPIOI_MODER_PI        ,val);
    val = ioread32(GPIOI_OTYPER_PI    );            printk("GPIOI_OTYPER_PI:%08X %08X\r\n",        GPIOI_OTYPER_PI        ,val);
    val = ioread32(GPIOI_OSPEEDR_PI    );            printk("GPIOI_OSPEEDR_PI:%08X %08X\r\n",    GPIOI_OSPEEDR_PI    ,val);
    val = ioread32(GPIOI_PUPDR_PI    );            printk("GPIOI_PUPDR_PI:%08X %08X\r\n",        GPIOI_PUPDR_PI        ,val);
    val = ioread32(GPIOI_ODR_PI        );            printk("GPIOI_ODR_PI:%08X %08X\r\n",        GPIOI_ODR_PI        ,val);
    val = ioread32(GPIOI_BSRR_PI    );            printk("GPIOI_BSRR_PI:%08X %08X\r\n",        GPIOI_BSRR_PI        ,val);

    val = ioread32(GPIOC_MODER_PI    );            printk("GPIOC_MODER_PI:%08X %08X\r\n",        GPIOC_MODER_PI        ,val);
    val = ioread32(GPIOC_OTYPER_PI    );            printk("GPIOC_OTYPER_PI:%08X %08X\r\n",        GPIOC_OTYPER_PI        ,val);
    val = ioread32(GPIOC_OSPEEDR_PI    );            printk("GPIOC_OSPEEDR_PI:%08X %08X\r\n",    GPIOC_OSPEEDR_PI    ,val);
    val = ioread32(GPIOC_PUPDR_PI    );            printk("GPIOC_PUPDR_PI:%08X %08X\r\n",        GPIOC_PUPDR_PI        ,val);
    val = ioread32(GPIOC_ODR_PI        );            printk("GPIOC_ODR_PI:%08X %08X\r\n",        GPIOC_ODR_PI        ,val);
    val = ioread32(GPIOC_BSRR_PI    );            printk("GPIOC_BSRR_PI:%08X %08X\r\n",        GPIOC_BSRR_PI        ,val);

    //spin_lock_irqsave(&lock, flags);    /* 上锁 */
   
    if(sta == LEDON) {
        val = readl(GPIOI_BSRR_PI);
        val |= (1 << (GPIO_PIN+16));   
        writel(val, GPIOI_BSRR_PI);
        
        val = readl(GPIOC_BSRR_PI);
        val |= (1 << (7+16));   
        writel(val, GPIOC_BSRR_PI);
        
    }else if(sta == LEDOFF) {
        val = readl(GPIOI_BSRR_PI);
        val|= (1 << GPIO_PIN);   
        writel(val, GPIOI_BSRR_PI);

        val = readl(GPIOC_BSRR_PI);
        val|= (1 << 7);   
        writel(val, GPIOC_BSRR_PI);

    }

    //spin_unlock_irqrestore(&lock, flags);/* 解锁 */   
}

/*
* @description        : 取消映射
* @return             : 无
*/
void led_unmap(void)
{
    printk("unmap the io\r\n");
    /* 取消映射 */
    iounmap(MPU_AHB4_PERIPH_LP_RCC_PI);

    iounmap(MPU_AHB4_PERIPH_RCC_PI);
    iounmap(GPIOI_MODER_PI);
    iounmap(GPIOI_OTYPER_PI);
    iounmap(GPIOI_OSPEEDR_PI);
    iounmap(GPIOI_PUPDR_PI);
    iounmap(GPIOI_ODR_PI);
    iounmap(GPIOI_BSRR_PI);
   
    iounmap(GPIOC_MODER_PI);
    iounmap(GPIOC_OTYPER_PI);
    iounmap(GPIOC_OSPEEDR_PI);
    iounmap(GPIOC_PUPDR_PI);
    iounmap(GPIOC_ODR_PI);
    iounmap(GPIOC_BSRR_PI);
   
}

/*
* @description        : 打开设备
* @param - inode     : 传递给驱动的inode
* @param - filp     : 设备文件,file结构体有个叫做private_data的成员变量
*                       一般在open的时候将private_data指向设备结构体。
* @return             : 0 成功;其他 失败
*/
static int led_open(struct inode *inode, struct file *filp)
{
    return 0;
}

/*
* @description        : 从设备读取数据
* @param - filp     : 要打开的设备文件(文件描述符)
* @param - buf     : 返回给用户空间的数据缓冲区
* @param - cnt     : 要读取的数据长度
* @param - offt     : 相对于文件首地址的偏移
* @return             : 读取的字节数,如果为负值,表示读取失败
*/
static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
    return 0;
}

/*
* @description        : 向设备写数据
* @param - filp     : 设备文件,表示打开的文件描述符
* @param - buf     : 要写给设备写入的数据
* @param - cnt     : 要写入的数据长度
* @param - offt     : 相对于文件首地址的偏移
* @return             : 写入的字节数,如果为负值,表示写入失败
*/
static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
    int retvalue;
    unsigned char databuf[1];
    unsigned char ledstat;

    retvalue = copy_from_user(databuf, buf, cnt);
    if(retvalue < 0) {
        printk("kernel write failed!\r\n");
        return -EFAULT;
    }

    ledstat = databuf[0];        /* 获取状态值 */

    if(ledstat == LEDON) {   
        led_switch(LEDON);        /* 打开LED灯 */
    } else if(ledstat == LEDOFF) {
        led_switch(LEDOFF);        /* 关闭LED灯 */
    }
    return 0;
}

/*
* @description        : 关闭/释放设备
* @param - filp     : 要关闭的设备文件(文件描述符)
* @return             : 0 成功;其他 失败
*/
static int led_release(struct inode *inode, struct file *filp)
{
    return 0;
}

/* 设备操作函数 */
static struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .open = led_open,
    .read = led_read,
    .write = led_write,
    .release =     led_release,
};

/*
* @description    : 驱动出口函数
* @param         : 无
* @return         : 无
*/
static int __init led_init(void)
{
    int retvalue = 0;
    u32 val = 0;
    u32 loop;

    /*  初始化自旋锁 */
    //spin_lock_init(&lock);
   
    //spin_lock_irqsave(&lock, flags);    /* 上锁 */
   
    /* 初始化LED */
    /* 1、寄存器地址映射 */
      MPU_AHB4_PERIPH_LP_RCC_PI = ioremap(RCC_MP_AHB4LPENSETR, 4);

      MPU_AHB4_PERIPH_RCC_PI = ioremap(RCC_MP_AHB4ENSETR, 4);
    GPIOI_MODER_PI = ioremap(GPIOI_MODER, 4);
      GPIOI_OTYPER_PI = ioremap(GPIOI_OTYPER, 4);
    GPIOI_OSPEEDR_PI = ioremap(GPIOI_OSPEEDR, 4);
    GPIOI_PUPDR_PI = ioremap(GPIOI_PUPDR, 4);
    GPIOI_ODR_PI = ioremap(GPIOI_ODR, 4);
    GPIOI_BSRR_PI = ioremap(GPIOI_BSRR, 4);

    GPIOC_MODER_PI         = ioremap(GPIOC_MODER, 4);
      GPIOC_OTYPER_PI     = ioremap(GPIOC_OTYPER, 4);
    GPIOC_OSPEEDR_PI     = ioremap(GPIOC_OSPEEDR, 4);
    GPIOC_PUPDR_PI         = ioremap(GPIOC_PUPDR, 4);
    GPIOC_ODR_PI         = ioremap(GPIOC_ODR, 4);
    GPIOC_BSRR_PI         = ioremap(GPIOC_BSRR, 4);

    /* 2、使能PI时钟 */
    val = readl(MPU_AHB4_PERIPH_RCC_PI);
    val &= ~(0X1 << 8);    /* 清除以前的设置 */
    val |= (0X1 << 8);    /* 设置新值 */
    writel(val, MPU_AHB4_PERIPH_RCC_PI);

    /* 3、设置PI0通用的输出模式。*/
    val = readl(GPIOI_MODER_PI);
    val &= ~(0X3 << (GPIO_PIN*2));    /* bit0:1清零 */
    val |= (0X1 << (GPIO_PIN*2));    /* bit0:1设置01 */
    writel(val, GPIOI_MODER_PI);

    /* 3、设置PI0为推挽模式。*/
    val = readl(GPIOI_OTYPER_PI);
    val &= ~(0X1 << (GPIO_PIN*1));    /* bit0清零,设置为上拉*/
    writel(val, GPIOI_OTYPER_PI);

    /* 4、设置PI0为高速。*/
    val = readl(GPIOI_OSPEEDR_PI);
    val &= ~(0X3 << (GPIO_PIN*2)); /* bit0:1 清零 */
    val |= (0x2 << (GPIO_PIN*2)); /* bit0:1 设置为10*/
    writel(val, GPIOI_OSPEEDR_PI);

    /* 5、设置PI0为上拉。*/
    val = readl(GPIOI_PUPDR_PI);
    val &= ~(0X3 << (GPIO_PIN*2)); /* bit0:1 清零*/
    val |= (0x1 << (GPIO_PIN*2)); /*bit0:1 设置为01*/
    writel(val,GPIOI_PUPDR_PI);

    /* 6、默认关闭LED */
    val = readl(GPIOI_BSRR_PI);
    val &= ~(0x1 << (GPIO_PIN*2));   
    writel(val, GPIOI_BSRR_PI);




    /* 2、使能PI时钟 */
    val = readl(MPU_AHB4_PERIPH_RCC_PI);
    val &= ~(0X1 << 2);    /* 清除以前的设置 */
    val |= (0X1 << 2);    /* 设置新值 */
    writel(val, MPU_AHB4_PERIPH_RCC_PI);

    /* 3、设置PI0通用的输出模式。*/
    val = readl(GPIOC_MODER_PI);
    val &= ~(0X3 << (7*2));    /* bit0:1清零 */
    val |= (0X1 << (7*2));    /* bit0:1设置01 */
    writel(val, GPIOC_MODER_PI);

    /* 3、设置PI0为推挽模式。*/
    val = readl(GPIOC_OTYPER_PI);
    val &= ~(0X1 << (7*1));    /* bit0清零,设置为上拉*/
    writel(val, GPIOC_OTYPER_PI);

    /* 4、设置PI0为高速。*/
    val = readl(GPIOC_OSPEEDR_PI);
    val &= ~(0X3 << (7*2)); /* bit0:1 清零 */
    val |= (0x2 << (7*2)); /* bit0:1 设置为10*/
    writel(val, GPIOC_OSPEEDR_PI);

    /* 5、设置PI0为上拉。*/
    val = readl(GPIOC_PUPDR_PI);
    val &= ~(0X3 << (7*2)); /* bit0:1 清零*/
    val |= (0x1 << (7*2)); /*bit0:1 设置为01*/
    writel(val,GPIOC_PUPDR_PI);

    /* 6、默认关闭LED */
    val = readl(GPIOC_BSRR_PI);
    val =  (0x1 << (7*2));   
    writel(val, GPIOC_BSRR_PI);
    //spin_unlock_irqrestore(&lock, flags);/* 解锁 */

    /* 6、注册字符设备驱动 */
    retvalue = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);
    if(retvalue < 0) {
        printk("register chrdev failed!\r\n");
        goto fail_map;
    }
   
    /* 2、使能PI时钟 */
    val = readl(MPU_AHB4_PERIPH_LP_RCC_PI);
    val &= ~(0X1 << 2);    /* 清除以前的设置 */
    val |= (0X1 << 2);    /* 设置新值 */
    writel(val, MPU_AHB4_PERIPH_LP_RCC_PI);
   
    for(loop=0;loop<50;loop++){
        val = ioread32(MPU_AHB4_PERIPH_RCC_PI);    printk("MPU_AHB4_PERIPH_RCC_PI:%08X\r\n",val);
        
        mdelay(500);
    }
   
   
    return 0;
   
fail_map:
    led_unmap();
    return -EIO;
}

/*
* @description    : 驱动出口函数
* @param         : 无
* @return         : 无
*/
static void __exit led_exit(void)
{
    /* 取消映射 */
    led_unmap();

    /* 注销字符设备驱动 */
    unregister_chrdev(LED_MAJOR, LED_NAME);
}

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ALIENTEK");
MODULE_INFO(intree, "Y");


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

10

主题

213

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
5607
金钱
5607
注册时间
2016-12-19
在线时间
724 小时
发表于 2022-3-31 17:08:32 | 显示全部楼层
有可能其他驱动里,在使用这个蜂鸣器.最好查查
回复

使用道具 举报

2

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2018-1-30
在线时间
10 小时
 楼主| 发表于 2022-3-31 18:24:24 | 显示全部楼层
你的蓝朋友 发表于 2022-3-31 17:08
有可能其他驱动里,在使用这个蜂鸣器.最好查查

我还是比较怀疑是有低功耗的功能,给关闭了那个寄存器的相关位。
回复

使用道具 举报

10

主题

213

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
5607
金钱
5607
注册时间
2016-12-19
在线时间
724 小时
发表于 2022-4-1 06:58:31 | 显示全部楼层
吕布MCU 发表于 2022-3-31 18:24
我还是比较怀疑是有低功耗的功能,给关闭了那个寄存器的相关位。

我觉得不是,那为什么LED不关呢?????
回复

使用道具 举报

1

主题

24

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
294
金钱
294
注册时间
2022-3-30
在线时间
44 小时
发表于 2022-4-1 09:49:50 | 显示全部楼层
这个PC7是应该是别的外设使用到了,可能是emmc相关的节点
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 10:14

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表