ioremap内存映射 始终不能访问内存 求解

isolated_bb 2011-03-07 03:29:41
ioremap内存映射,修改了数次,还是不能正常访问寄存器,基本问题是可以加载模块,但是只要lsmod就会出现段错误
unable to handle kernel paging request at virtual address 7fXXXXXX
望高手指教!!!

#include <asm/io.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/device.h>
#include <linux/gpio.h>

static int led_major;
static void *base;
#define LED_CONTROLLER_BASE 0x56000050
#define led_all_off 0
#define led_all_on 1
#define DEVICE_NAME "zx_led"
#define LED_CON (*(volatile u32*)(LED_CONTROLLER_BASE))
#define LED_DAT (*(volatile u32*)(LED_CONTROLLER_BASE + 4))
#define LED_UP (*(volatile u32*)(LED_CONTROLLER_BASE + 8))
#define LED_MEM_LEN 0x0c
static int led_open(struct inode *inode,struct file *file)
{
printk("the led driver is open\n");
return 0;
}
static int led_close(struct inode *inode,struct file *file)
{
printk("the led driver is close\n");
return 0;
}
static int led_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
{
switch(cmd)
{
case led_all_off:
//iowrite16(0x00,base + 0x04);
iowrite16((ioread16(base + 0x04)&0xff)|0x0,base + 0x04);
break;
case led_all_on:
iowrite16(0x0f00,base + 0x04);
iowrite16((ioread16(base + 0x04)&0xff)|0xff00,base + 0x04);
break;
default:
return -EINVAL;
}
return 0;
}

static struct file_operations led_fops =
{
.owner = THIS_MODULE,
.open = led_open,
.ioctl = led_ioctl,
.release= led_close,
};

static struct class *led_class;
static int led_init(void)
{
printk("led initialize\n");
led_major = register_chrdev(0, DEVICE_NAME, &led_fops);
if(led_major < 0)
{
printk("can't creat led_major\n");
return led_major;
}
printk("register zhengxu_led Driver OK! Major = %d\n", led_major);
led_class = class_create(THIS_MODULE,DEVICE_NAME);
if(IS_ERR(led_class))
{
printk("led_class create is failed\n");
return -1;
}
printk("class_create is ok\n");
device_create(led_class, NULL, MKDEV(led_major, 0), NULL, DEVICE_NAME);
printk("initialize is sucessful\n");
request_mem_region(LED_CONTROLLER_BASE,LED_MEM_LEN,"zx_led");
base=ioremap_nocache(LED_CONTROLLER_BASE,LED_MEM_LEN);
printk("%lx\n",base);
printk("ioremap is sucessful\n");
if(base < 0)
{
printk("ioremap is failed\n");
}
// iowrite16(0xff00,base);
iowrite16((ioread16(base)&0xff00)|0x00ff,base);
// iowrite16(0xff00,base + 0x08);
iowrite16((ioread16(base + 0x08)&0xff)|0xff00,base + 0x08);
return 0;
}
void led_exit(void)
{
unregister_chrdev(led_major,DEVICE_NAME);
device_destroy(led_class,MKDEV(led_major,0));
class_destroy(led_class);
iounmap(base);
release_mem_region(LED_CONTROLLER_BASE,LED_MEM_LEN);
}

module_init(led_init);
module_exit(led_exit);
MODULE_AUTHOR("zhengxu");
MODULE_LICENSE("GPL");

...全文
1520 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
lihaoweiV 2011-11-06
  • 打赏
  • 举报
回复
请问楼主解决了问题了没, 如果解决了, 希望能共享一下答案。 拜托了
sy00800 2011-06-24
  • 打赏
  • 举报
回复
是不是你的ioremap的第二个参数不太对?
guolele2010 2011-03-08
  • 打赏
  • 举报
回复
你没有检测request_mem_region这函数返回值,它可能不能申请到那块内存空间,这样当然会失败
isolated_bb 2011-03-08
  • 打赏
  • 举报
回复
6楼说的是不是这个意思 直接对这个端口变量进行赋值从而达到对寄存器的访问???
我随便写了个例子
(*(volatile unsigned long *)S3C2410_GPBDAT) = 0xXX
这里的S3C2410_GPBDAT并不是你端口的实际地址吧(物理地址)??它需要有BSP(板级支持包)的支持,然后映射到虚拟地址区域的一个虚拟地址 所以它本质上应该还是个虚拟地址也就是0xc0000000以上的地址 虽然内核中没有对它进行ioremap的映射,是因为ARM体系结构是统一编制的??寄存器与内核地址空间本身就存在着固定地址的偏移??所以这样的操作也是对虚拟地址操作从而控制寄存器的状态!!
而我的目的是通过ioremap函数来映射到内核地址空间,然后修改虚拟地址空间达到控制寄存器的状态的目的,如果用BSP支持的话,我是可以正常访问的,但是如果没有BSP支持呢?我就是想实验下ioremap函数,不知确出现这么多的问题......
以上只属个人意见,不对之处,欢迎指出,本人虚心接受
isolated_bb 2011-03-08
  • 打赏
  • 举报
回复
呃....我明白你的意思了 但是直接对指针赋值的话 我看了很多参考文献 都说这样会很不好...一定要用标准的IO函数...并且应该不是 访问IO的问题 我再好好检查一下我的指针吧 也许不是ioremap的问题
steven_miao 2011-03-08
  • 打赏
  • 举报
回复
你说的意思我明白,我没有试过采用ioreab16这个来读取寄存器值,而是将ioremap后的指针直接使用的。如
base_addr= ioremap(xx,xx);
#define xx (*(volatile unsigned long *)(base_addr + 0x00))这样来用的。
然后赋值采用xx = 1;和temp=xx来实现寄存器的读写。不过应该还可以使用
struct regs
{
unsigned long reg1;
unsigned long reg2;
....
};
struct regs *regster;

register=(struct regs *)base_addr;
不过这个我没有试过,理论上是可以的,因为base_addr是内核虚拟地址。
steven_miao 2011-03-08
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 isolated_bb 的回复:]

6楼说的是不是这个意思 直接对这个端口变量进行赋值从而达到对寄存器的访问???
我随便写了个例子
(*(volatile unsigned long *)S3C2410_GPBDAT) = 0xXX
这里的S3C2410_GPBDAT并不是你端口的实际地址吧(物理地址)??它需要有BSP(板级支持包)的支持,然后映射到虚拟地址区域的一个虚拟地址 所以它本质上应该还是个虚拟地址也就是0xc0……
[/Quote]
S3C2410_GPBDAT就是ioremap返回的虚拟地址。
手机写程序 2011-03-08
  • 打赏
  • 举报
回复
if(!request_mem_region(LED_CONTROLLER_BASE,LED_MEM_LEN,"zx_led"))
{
printk("request_mem_region failed,pls check LED_CONTROLLER_BASE.\n");
return -1;
}
isolated_bb 2011-03-08
  • 打赏
  • 举报
回复
我在/proc/iomem下可以看到申请的端口 并且我也添加了打印信息 所以应该不是这个问题 但还是谢谢你的回答
isolated_bb 2011-03-07
  • 打赏
  • 举报
回复
首先 感谢大家回复!! (arm(2440)+linux)
我所粘贴的信息是我串口打印出来的全部的错误信息了,我也不知道具体的错误在哪里,但是只要注释掉ioremap就没有任何问题了(当然内存也无法映射了),因为编译的时候没有什么错误信息提示,加载内核模块的时候(insmod)也没有,只是查询模块挂载(lsmod)或者卸载模块的时候(rmmod)就会出现以上的错误信息
对于6楼的话我不是很理解,直接定义访问?那么访问的是I/O端口还是I/O内存?我认为你访问的是端口,I/O内存不是必须经过映射转化为虚拟地址才能访问么?ARM体系中不存在I/O端口吧?所以只要是寄存器的访问通通都要先映射?后访问虚拟内存空间??我程序的意思也是这样,先将寄存器的物理地址映射到虚拟内存空间,然后对虚拟内存空间进行访问,从而达到访问寄存器的目的!!!并且ioremap的返回地址也是对的(C4848050)是在3G以上的内核空间!!可是错误信息中提示"无法处理此时的请求页面调度的内核虚拟地址9f3008f7,这个是一个用户空间的地址",我是真不知道是怎么个情况了.....以上是个人理解 不知道对不对 还望请教 继续讨论
steven_miao 2011-03-07
  • 打赏
  • 举报
回复 1
是可以用ioremap去映射物理内存的,不过base的类型好像是 void __iomem *啊!还有啊,最好多用printk打印程序执行到哪儿出问题了,我一般直接用ioremap。
可以这样定义后就可以直接读值和写值,就把它当做一个变量就可以了。不过你也可以直接搞成结构体类型也成。
#define ADCCON (*(volatile unsigned long *)(base_addr + 0x00))
Wenxy1 2011-03-07
  • 打赏
  • 举报
回复
把错误多贴一点,感觉不是ioremap内存不能访问, ioremap用来映射IO的.
ezword 2011-03-07
  • 打赏
  • 举报
回复
使用gdb定位下,看看是哪句话出了问题。
isolated_bb 2011-03-07
  • 打赏
  • 举报
回复
unable to handle kernel paging request at virtual address 9f3008f7
pgd = c18b0000
[9f3008f7] *pgd = 00000000
INternal error : oops 5 [#1]


以上就是错误信息
isolated_bb 2011-03-07
  • 打赏
  • 举报
回复
unable to handle kernel paging request at virtual address 9f3008f7
pgd = c18b0000
[9f3008f7] *pgd = 00000000
INternal error : oops 5 [#1]
无知者无谓 2011-03-07
  • 打赏
  • 举报
回复
[Quote=引用楼主 isolated_bb 的回复:]
unable to handle kernel paging request at virtual address 7fXXXXXX
[/Quote]

信息太少
另[ code=C/C++ ]代码是复制到这的[ /code ]
内容概要:本文系统研究了线性模型预测控制(LMPC)与非线性模型预测控制(NMPC)在四旋翼无人机轨迹跟踪任务中的控制性能对比,基于Matlab/Simulink平台搭建完整的仿真控制系统。研究内容涵盖四旋翼无人机的动力学建模、状态空间表达、线性与非线性预测模型构建、滚动时域优化求解以及系统约束处理等关键技术环节,重点从轨迹跟踪精度、动态响应速度、系统稳定性及抗干扰能力等方面对两种控制策略进行对比分析,深入探讨线性化近似方法与精确非线性模型在实际控制效果上的差异,为无人机高性能飞控系统的设计提供理论支撑与仿真验证依据; 适合人群:具备自动控制原理、非线性系统理论、无人机动力学及Matlab/Simulink仿真基础的研究生、科研人员以及从事无人飞行器控制算法开发的工程技术人员; 使用场景及目标:① 掌握模型预测控制(MPC)在强非线性系统如四旋翼中的具体应用方法;② 理解LMPC与NMPC在建模假设、优化求解及控制性能上的本质差异;③ 为相关课题的仿真系统搭建、控制算法选型与性能评估提供实践参考;④ 支持课程设计、学位论文撰写或科研项目的算法验证与结果分析; 阅读建议:建议结合提供的Simulink仿真模型,深入剖析状态预测、代价函数设计与实时滚动优化的实现机制,对比不同飞行工况(如高机动轨迹)下的仿真结果,重点关注NMPC在复杂动态环境中的性能优势以及LMPC在计算效率与实时性方面的潜力,同时应注意非线性优化带来的计算负担问题及其对工程可实现性的影响。
内容概要:本文档为一篇关于“基于超局部模型无模型预测电流控制(MFPCC)+自抗扰ESO观测器改进模型预测控制仿真”的论文复现资源,重点介绍了在Simulink环境下对三相逆变器系统进行建模与控制策略仿真的研究。核心内容聚焦于采用无模型预测电流控制(MFPCC)结合自抗扰控制中的扩张状态观测器(ESO)来提升系统对参数不确定性与外部干扰的鲁棒性,优化电流环动态响应性能。文中通过构建超局部模型规避精确系统建模的难题,利用MFPCC实现快速动态响应,并引入ESO实时估计并补偿系统内外部扰动,从而增强整体控制精度与稳定性。通过与传统控制方法的对比仿真,充分验证了该复合控制策略在抑制扰动、提高电流跟踪精度及改善系统鲁棒性方面的优越性,文档同时提供了完整的Simulink仿真模型与实现代码,便于读者复现、调试与深入研究。; 适合人群:具备电力电子、自动控制理论基础,熟悉Simulink仿真环境,从事电机控制、新能源并网、电力变换器控制或预测控制算法研究的研究生、科研人员及工程技术人员。; 使用场景及目标:① 复现并掌握MFPCC与ESO相结合的先进复合控制策略;② 深入研究无模型预测控制在电力电子系统中的具体应用与实现方法;③ 探索自抗扰控制中ESO观测器在扰动估计与补偿、提升系统鲁棒性方面的关键作用与设计要点;④ 作为毕业设计、科研课题、学术论文复现或工程项目开发的重要技术参考与原型验证平台。; 阅读建议:建议读者结合现代控制理论与电力电子技术基础知识,首先深入理解MFPCC的无模型预测原理与ESO的扰动观测机理,再逐步导入并调试所提供的仿真模型,重点关注控制器参数的整定过程、系统在不同工况下的抗扰性能测试与动态响应指标分析,同时可参考文档中列出的其他相关案例进行横向比较与综合学习,以达到融会贯通的效果。

4,469

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧