不会LINUX,但是我还要调试内核
本帖最后由 yjmwxwx 于 2019-1-24 23:26 编辑不是说学习LINUX么,但是我不会C语言啊,汇编能不能搞LINUX ?
先不说这个,还是调试下 明远什么睿的那个EK140迷你版IMX6ULL,但是你怎么给把JTAG口给关了啊,在哪里关的啊? 懒得问他们,我在淘宝买的,那个MM根本不懂技术,问她这种问题肯定解决不了。
就这一个简单问题上网搜吧,google ,yandex ,baidu 美俄中三大搜索没搜到,只搜到这个https://community.nxp.com/thread/376786 说让改imx6q_set_lpm,刚学内核也不懂C语言怎么改啊,看了看手册然后看汇编找到寄存器,把这个函数跳过去吧,要改机器码还要解压内核,我这内核是LZO的,解压后再同样参数打包,下载进去直接不运行了,看样子有校验。。
没办法还是得用官方固件调试,发现第三个灯灭JLINK就自动断开,于是上土法,终于找到了开关LED和关闭JLINK的地方,原来JLINK是在imx_pmx_set里面关闭的。
开关GPIO5上LED的函数
关闭JLINK的地方
通过调试发现开关led操作的是0X90850000,这是怎么回事,不是应该0X20AC000么? 怎么变过去的啊,后来网络搜索说是啥设备树页表什么的,我根本不懂啊,没办法先自学下吧,我自学从来不看网上的视频,我都是看书或者手册,先把参考手册和构架手册转成中文,有点大快7000页,也不知道什么人写的,让人怎么看啊。。 于是网上搜啊搜搜到个韩国人的博客,我不懂C语言不可能去一个函数一个函数的读内核,这个就看韩国人读吧。。
http://jake.dothome.co.kr/
先学习设备树,然后调试跟踪这个到底怎么变过去的啊,调啊调,内核函数比较绕,转来转去也没找到哪里变的走了弯路。
后来才知道原来是虚拟地址转物理地址的问题啊,真是的没学过操作系统,没往这方面想。。
也是从头开始从内涵那个汇编文件跟踪看看到底怎么初始化的,经过比较坎坷,后来知道页表作怪,又跟踪paging_init,这个函数也比较绕太垃圾了,没办法缩小范围到create_mapping,经过跟踪发现这个函数向0X80006000写一些数据,每个间隔0x100000,写了很多难道这个就是传说中的页表?
这是什么啊,光听网上大神门说页表页表的,这东西到底什么样子?
简单点问题0X90850000怎么变成0X20AC000的??
后来韩国人博客看到下面这张图片
不知道大家刚学页表的看不看的懂,反正我是没看懂,我这个和他这个地址不一样啊,也没啥文字描述让人怎么看啊。。
还是上土法,调试,搜索内存,写个程序把页表清零,看看到底哪个地址起的作用,就顺着0X90850000这条线索追踪,最后逐渐缩小范围,目标锁定在0X80006420上面,这地址里面是0X88005811,这个地址怎么变成0X20AC00的啊,还是不清晰,继续搜索内存,搜0X20AC,这次搜到了,原来在0X88005940,里面是0X20AC453。
结合这个关系才看明白前面韩国人那个图
自己总结了下计算经过
===============================================================
GPIO5_DR的虚拟地址是0x90850000
拆分成 从高向低分别是0x908, 0x50, 0x000
TTBR里面是0x8000406a
命令 mrc p15, 0, r0, c2, c0, 0 读TTBR0到R0
mrc p15, 0, r1, c2, c0, 1 读TTBR1到R1
第一级
TTBR的0到9位清0等于0x80004000
0x908乘4等于0x2420,
0x2420加0x80004000等于0x80006420
第二级
内存地址0x80006420里面的数据是0x88005811
0x88005811的0到9位清0等于0x88005800
0x50乘4等于0x140
0x88005800加0x140等于0x88005940
第三级
地址0x88005940里面的数据是0x20ac453
0x20ac453的0到11位清0等于0x20ac000
0x20ac000加前面的0x000等于0x20ac000也就是说前面这个直接是物理地址。
到这里0x90850000虚拟地址转成了物理地址0x20ac000也就是GPIO5_DR
怎么样有了实物容易理解了吧,解决了这个跟踪起来就清晰多了,以前学过的前辈看看我计算的对不对??
本帖最后由 yjmwxwx 于 2019-1-28 01:18 编辑
验证下自己改虚拟地址,短描述符格式,两级描述符。 GPIO5虚拟地址0X10000000第一级描述符0X80004811写到0X80004400 第二级0X20AC453写到0X80004800。程序实现虚拟地址LED灯闪烁。
.syntax unified
.arch armv7-a
.align 4
.arm
.text
movw r6, # 0x4000
movt r6, # 0x8000 @ r6 = 0x80004000
mov r0, r6 @ r0 读 r6
mov r4, # 1000 @ 10K内存
mov r5, # 0 @ 10K内存写0
_nei_cun_qing_ling: @ 循环写0函数
str r5, , # 0x04 @ R5= 0 写到R6的地址然后地址加4
subs r4, r4, # 1 @ 执行一次计数减1
bne _nei_cun_qing_ling @ 不等与0循环
movw r1, # 0x4811
movt r1, # 0x8000 @ r1 = 0x80004811 第一级描述符
add r0, r0, # 0x400 @ 0x80004000 加 0x400 = 0x80004400
str r1, @ 第一级描述符写到0x80004400
movw r1, # 0xc453
movt r1, # 0x020a @ r1 = 0x20ac453 第二级描述符
add r0, r0, # 0x400 @ 0x80004400 加 0x400 = 0x80004800
str r1, @ 第二级描述符写到0x80004800
movw r0, # 0x406a
movt r0, # 0x8000 @ r0= 0x8000406a
mcr p15, 0, r0, c2, c0, 0 @ r0写到TTBR0
mcr p15, 0, r0, c2, c0, 1 @ r0写到TTBR1
movw r0, # 0x3C7D
movt r0, # 0x10C5 @ r0 = 0x10c53c7d
mcr p15, 0, r0, c1, c0, 0 @ 打开MMU
movw r0, # 0x0000
movt r0, # 0x1000 @ GPIO5_DR虚拟地址= 0x10000000
_led_kai_guan: @ LED闪烁程序
mov r1, # 0x10 @ IO4
str r1, @ IO4配置为输出
str r1, @ IO4开
mov r3, # 0x00 @
movw r2, # 0xffff
movt r2, # 0x03ff @ R2 = 延时数0x3ffffff
_led_xun_huan1: @ IO开延时
subs r2, r2, # 1 @ R2减1
bne _led_xun_huan1 @ 开延时循环
str r3, @ 延时结束关闭IO4
movw r2, # 0xffff
movt r2, # 0x03ff @ 延时数重新写入R2
_led_xun_huan2: @ IO关延时
subs r2, r2, # 1 @ R2减1
bne _led_xun_huan2 @ 关延时循环
b _led_kai_guan @ 跳转到LED函数
完全看不懂 yjmwxwx 发表于 2019-1-28 01:14
验证下自己改虚拟地址,短描述符格式,两级描述符。 GPIO5虚拟地址0X10000000第一级描述符0X80004811写到0X ...
任性
页:
[1]