luckfox pico plus (RV1103) 使用ioremap做4字节地址映射后、readl只能读出2个字节的有效数据
Posted: 2024-07-06 8:16
luckfox pico plus (RV1103) 编写IO控制驱动(直接操作寄存的方式),使用ioremap做4字节地址映射后、readl只能读出2个字节的有效数据(用printk打印,高2个字节为空),导致后续对寄存器的操作失败。
串口log:
# insmod led.ko
[ 2256.146492] GPIO3C6_IOMUX = 3002
[ 2256.146525] GPIO3C6_IOMUX = 3002
[ 225# 6.146609] led_init!
具体部分代码如下。
可行是什么原因?
=========================================================================
/*GPIO3C6寄存器物理地址 */
#define GPIO3C6_IOMUX_BASE (0xFF558054)
#define GPIO3C6_PULL_BASE (0xFF5581E8)
#define GPIO3C6_MODE_BASE (0xFF55000C)
#define GPIO3C6_OUTPUT_BASE (0xFF550004)
#define GPIO3C6_INPUTCTRL_BASE (0xFF5581A8)
#define GPIO3C6_SCHMITT_BASE (0xFF5582A8)
#define GPIO3C6_DRIVESTRENGTH_BASE (0xFF55812C)
/*地址映射后的虚拟地址*/
static void __iomem *GPIO3C6_IOMUX;
static void __iomem *GPIO3C6_PULL;
static void __iomem *GPIO3C6_MODE;
static void __iomem *GPIO3C6_OUTPUT;
static void __iomem *GPIO3C6_INPUTCTRL;
static void __iomem *GPIO3C6_SCHMITT;
static void __iomem *GPIO3C6_DRIVESTRENGTH;
//设置GPIO3C6输出高电平,点亮LED灯
static int __init led_init(void)
{
int ret = 0;
unsigned int var = 0;
/*1、建立地址映射*/
GPIO3C6_IOMUX = ioremap(GPIO3C6_IOMUX_BASE, 4);
GPIO3C6_PULL = ioremap(GPIO3C6_PULL_BASE, 4);
GPIO3C6_MODE = ioremap(GPIO3C6_MODE_BASE, 4);
GPIO3C6_OUTPUT = ioremap(GPIO3C6_OUTPUT_BASE, 4);
GPIO3C6_INPUTCTRL = ioremap(GPIO3C6_INPUTCTRL_BASE, 4);
GPIO3C6_SCHMITT = ioremap(GPIO3C6_SCHMITT_BASE, 4);
GPIO3C6_DRIVESTRENGTH = ioremap(GPIO3C6_DRIVESTRENGTH_BASE, 4);
/*2、初始化*/
var = readl(GPIO3C6_IOMUX);
printk("GPIO3C6_IOMUX = %8x\r\n", var); //打印GPIO3C6_IOMUX的出初始值
var &= ~(7<<8); //清除 bit 8~10
writel(var, GPIO3C6_IOMUX);
printk("GPIO3C6_IOMUX = %8x\r\n", var); //打印GPIO3C6_IOMUX修改后的值
var = readl(GPIO3C6_PULL);
var &= ~(3<<12); //清除 bit 12~13, 即值设置为0
writel(var, GPIO3C6_PULL);
var = readl(GPIO3C6_MODE);
var |= 1<<6; //将bit 6 的值设置为 1 输出
writel(var, GPIO3C6_MODE);
var = readl(GPIO3C6_OUTPUT);
var |= 1<<6; //将bit 6 的值设置为 1 输出高点平
writel(var, GPIO3C6_OUTPUT);
var = readl(GPIO3C6_INPUTCTRL);
var &= ~(1<<6); //将bit 6 的值设置为 0 关闭输入
writel(var, GPIO3C6_INPUTCTRL);
var = readl(GPIO3C6_SCHMITT);
var |= 1<<6; //将bit 6 的值设置为 1 使能施密特触发器
writel(var, GPIO3C6_SCHMITT);
var = readl(GPIO3C6_DRIVESTRENGTH);
var |= 63; //将bit 0~5 的值设置为 63
writel(var, GPIO3C6_DRIVESTRENGTH);
ret = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);
if(ret < 0){
printk("register_chrdev failed!\r\n");
return -EIO;
}
printk(KERN_EMERG"led_init!\n");
return 0;
}
=========================================================================
串口log:
# insmod led.ko
[ 2256.146492] GPIO3C6_IOMUX = 3002
[ 2256.146525] GPIO3C6_IOMUX = 3002
[ 225# 6.146609] led_init!
具体部分代码如下。
可行是什么原因?
=========================================================================
/*GPIO3C6寄存器物理地址 */
#define GPIO3C6_IOMUX_BASE (0xFF558054)
#define GPIO3C6_PULL_BASE (0xFF5581E8)
#define GPIO3C6_MODE_BASE (0xFF55000C)
#define GPIO3C6_OUTPUT_BASE (0xFF550004)
#define GPIO3C6_INPUTCTRL_BASE (0xFF5581A8)
#define GPIO3C6_SCHMITT_BASE (0xFF5582A8)
#define GPIO3C6_DRIVESTRENGTH_BASE (0xFF55812C)
/*地址映射后的虚拟地址*/
static void __iomem *GPIO3C6_IOMUX;
static void __iomem *GPIO3C6_PULL;
static void __iomem *GPIO3C6_MODE;
static void __iomem *GPIO3C6_OUTPUT;
static void __iomem *GPIO3C6_INPUTCTRL;
static void __iomem *GPIO3C6_SCHMITT;
static void __iomem *GPIO3C6_DRIVESTRENGTH;
//设置GPIO3C6输出高电平,点亮LED灯
static int __init led_init(void)
{
int ret = 0;
unsigned int var = 0;
/*1、建立地址映射*/
GPIO3C6_IOMUX = ioremap(GPIO3C6_IOMUX_BASE, 4);
GPIO3C6_PULL = ioremap(GPIO3C6_PULL_BASE, 4);
GPIO3C6_MODE = ioremap(GPIO3C6_MODE_BASE, 4);
GPIO3C6_OUTPUT = ioremap(GPIO3C6_OUTPUT_BASE, 4);
GPIO3C6_INPUTCTRL = ioremap(GPIO3C6_INPUTCTRL_BASE, 4);
GPIO3C6_SCHMITT = ioremap(GPIO3C6_SCHMITT_BASE, 4);
GPIO3C6_DRIVESTRENGTH = ioremap(GPIO3C6_DRIVESTRENGTH_BASE, 4);
/*2、初始化*/
var = readl(GPIO3C6_IOMUX);
printk("GPIO3C6_IOMUX = %8x\r\n", var); //打印GPIO3C6_IOMUX的出初始值
var &= ~(7<<8); //清除 bit 8~10
writel(var, GPIO3C6_IOMUX);
printk("GPIO3C6_IOMUX = %8x\r\n", var); //打印GPIO3C6_IOMUX修改后的值
var = readl(GPIO3C6_PULL);
var &= ~(3<<12); //清除 bit 12~13, 即值设置为0
writel(var, GPIO3C6_PULL);
var = readl(GPIO3C6_MODE);
var |= 1<<6; //将bit 6 的值设置为 1 输出
writel(var, GPIO3C6_MODE);
var = readl(GPIO3C6_OUTPUT);
var |= 1<<6; //将bit 6 的值设置为 1 输出高点平
writel(var, GPIO3C6_OUTPUT);
var = readl(GPIO3C6_INPUTCTRL);
var &= ~(1<<6); //将bit 6 的值设置为 0 关闭输入
writel(var, GPIO3C6_INPUTCTRL);
var = readl(GPIO3C6_SCHMITT);
var |= 1<<6; //将bit 6 的值设置为 1 使能施密特触发器
writel(var, GPIO3C6_SCHMITT);
var = readl(GPIO3C6_DRIVESTRENGTH);
var |= 63; //将bit 0~5 的值设置为 63
writel(var, GPIO3C6_DRIVESTRENGTH);
ret = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);
if(ret < 0){
printk("register_chrdev failed!\r\n");
return -EIO;
}
printk(KERN_EMERG"led_init!\n");
return 0;
}
=========================================================================