Pony279 发表于 2011-12-27 02:45:48

用Keil MDK开发TQ2440裸机程序入门教程2(移植TQ2440测试程序)

贴图真的有点辛苦, 想早点睡觉, 我就直接上文档了, 大家别喷我...

点击此处下载 ourdev_707860MDMXSN.doc(文件大小:810K) (原文件名:用Keil MDK开发TQ2440裸机程序入门教程2(移植TQ2440测试程序).doc)

也可以参考这个链接:

http://www.armbbs.net/forum.php?mod=viewthread&tid=10500&page=1&extra=#pid59267

之前发过的两个相关的帖子
教程1: http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=5281512&bbs_page_no=1&search_mode=3&search_text=Pony279&bbs_id=9999
求助贴(都没人理我的..../emotion/em072.gif):http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=5302644&bbs_page_no=1&search_mode=3&search_text=Pony279&bbs_id=9999

如果有什么错误, 欢迎指正...


刚刚写好的...累死, 睡觉去, 下周期末考, 好好复习...555...

补充内容 (2012-3-30 16:54):
部分内容有误,见14楼。

Pony279 发表于 2011-12-27 02:51:10

差点忘了上程序了...
点击此处下载 ourdev_707861PB556B.zip(文件大小:2.51M) (原文件名:TQ2440_Test.zip)

jordonwu 发表于 2011-12-27 08:46:56

mark,学习

Pony279 发表于 2011-12-29 19:03:56

今天有闲情了, 把内容贴上来./emotion/em018.gif

主要内容:

一. 有关启动的原理介绍(如果你是老鸟, 完全可以跳过的)

二. 复制代码, 建立并配置工程

三. 修改部分代码

四. 测试结果


前段时间发了这个教程:
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=5281512&bbs_page_no=1&search_mode=3&search_text=Pony279&bbs_id=9999
把标题定为教程实在是我自夸了点, 其实应该算是我学习的总结吧, 写份文档, 自己以后忘了也有个参考, 又可以帮助和我卡在同一个问题的新手, 其实我也是新手, 新手教新手, 不知道会不会误导大家了...

一. 有关启动的原理介绍
    那个教程里面主要讲了一些简单的配置, 原理没有仔细介绍, 其实当时我也不太懂, 当时看重的是实际效果, 原理嘛, 在我们从SB到NB的过程会慢慢理解的,
现在稍微理解了一点, 在写这篇教程之前简单介绍一下之前的存储器的地址配置的问题吧, 也和等会移植的内容有关啦, 耐心看吧:
TQ2440开发板算起来应该是有3个片外存储器吧, 一个是 nand flash, 一个是 nor flash, (这两个应该算是ROM了), 还有一个SDRAM (就是RAM啦, SDRAM是个什么东西, 还没学数电...不知道...)
2440算是冯诺什么曼结构的计算机, 通俗的说, 2440的程序代码是可以放在RAM里面执行(我们的PC机也是这种类型的), 不同于51, 也许你会注意到, 51的程序是不能在内部的RAM里面执行的, 现在的51单片机的程序一般是存在片内的ROM里的, 传统的51的内部RAM顶多也就那么256个字节, 变量都存不了几个, 运行个鬼程序, 51单片机算是哈佛结构的. (计算机基础不好, 欢迎批评指正)
其实我说这些只是为了说明...2440的程序代码是可以存放在SDRAM里面运行的.从汇编上讲, 就是程序指针(PC指针, 程序计数器, 各种称呼, 指向一下条要执行的程序代码 的一个寄存器)可以指到SDRAM的内存单元.
然后再说nor flash, 2440的程序也可以在nor flash里执行, 原因我不清楚. 从nor flash启动的时候, PC指向的0地址就是nor flash的首地址, 就是说nor flash 的首地址映射到内存的0地址,
对比一下SDRAM, SDRAM在2440是映射到0x3000 0000 地址
然后是nand flash, nand flash 也是映射到了 0地址, 这样就和nor flash有冲突了, 所以就有了从nor 启动和从nand启动的区别了,
然后我又想说, 其实nand本身是不能运行程序的(这里的意思是说, 因为nor flash本身为了容量大和本身的接口, 是不能向CPU不断的快速的输送指令的, 我的理解就是这样, 大家可以去参考nor 和 nand 的区别的资料), 既然我说nand不能运行程序, 那个地址映射有什么意义? 是这样的, 2440从nand启动的时候, 它内部的nand flash控制器会把前4k的代码复制到内部的缓存去执行, 而这些缓存就是对应地址的0单元开始. (其实这个直接去参考2440 datasheet 上的地址映射会比看我在这里瞎说的强...)

刚才说了从nand启动的时候是把前4k的代码复制到内部的缓存去执行的, nand flash的容量远远远远大于4K呀, 不充分利用就太浪费了...如果你的程序超过4K了怎么办? 很简单, 你在前4K的程序里, 利用什么for啊while之类的把剩下的代码复制到SDRAM里面去, 复制完了以后后再用一条汇编指令 ldr (用来跳转到绝对地址的, 类似C语言的goto, 但有点区别) 跳到SDRAM里面继续执行, (因为前4K的代码在内部缓存运行的时候对应的地址是从0-4K的, SDRAM是的地址是从0x30000000开始的, 你不跳, 就等着系统崩溃吧).
刚才说的这些工作你可以自己写代码, 也可以移植个boot loader来帮你做, 操作系统就是从boot loader开始的...这部分我没学, 不说了...

那么ldr指令是怎么跳转的? 在2440init.s里有这两句,
ldr        pc, =copy_proc_beg
copy_proc_beg
类似C语言的
goto copy_proc_beg
copy_proc_beg:
注意, 我说的是类似, 从汇编层面是讲, 是有很大的不同的, 我比较懒, 就不详细解释了
上面的ldr 的作用就是:
你的工程最后生成可执行的代码里面,copy_proc_beg 对应的地址(绝对地址, 就是说应该放在存储器的哪个位置), 会被复制到PC指针, 所以我们在nand启动的工程配置里, rom应该是这样的:
srart(开始): 0x30000000    size(大小, 我这里是随便设置的): 0x800000
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708775YE0JOJ.png
(抱歉, 我之前的教程里的生成下载到nand的bin的那部分配置讲错了, 当时并不理解, 不过, 小于4K的程序还是可以用的了^_^)
这样, 编译器生成以后, 标号copy_proc_beg对应的地址是0x3*******, 也就是在SDRAM里面, 然后你在去年前4k的时候PC指针的内容是0x00000***, 完成之前说的代码从nand flash到SDRAM的搬移工作后, 用一条 ldr        pc, =copy_proc_beg 指令, 把PC指针的内容改成0x3*******, 就跳转到SDRAM里面运行了
////////////////////////////////////////////////////////////////
补充: 其实教程1那里的只有把ROM配置成从0x0开始才是可以正常运行的, 原因是用了KEIL给的启动代码, 有一句是这样的
                IMPORT__main; 相当于extern void main()
                LDR   R0, =__main; 跳到main函数的绝对地址去执行
如果rom 设置 0x3000 0000 开始的话, 教程1的代码里又没有进行搬移的工作, 跳到SDRAM里去, 没有代码, 程序就不能正常运行了
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
补充:
用JLINK在SDRAM调试的时候, ROM配置也是
srart(开始): 0x30000000    size(大小, 我这里是随便设置的): 0x800000
然后你按下调试键的时候, 代码由J-LINK帮你复制到SDRAM了, 然后再把PC指到0X30000000开始执行, 这J-LINK的这些工作是由一个初始化文件(教程1里配置的时候从keil的安装目录那边复制过来的文件)指导完成的. 如果你在调试的时候按了这个键http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708776O7W244.png
就把单片机给复位了, 然后PC指针指向的地址就是0, 如果你再点运行,
除非你的nand flash 或 nor flash里面有程序, 要不然是不会正常运行的, 即使有程序, 也不能正常调试, 你要把PC指针改回0x30000000才可以让2440继续跑你要调试的程序, (双击PC又边的数字 0x00000000就可以改他的值了)
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708777NB1FGC.png

关于nor flash的设置, 没什么好讲的了, 从0开始执行, 嗯, 就这样了
////////////////////////////////////////////////////////////////


二. 复制代码, 建立并配置工程

    现在进入正题了, 其实主要讲的就是操作过程:
    (虽然很多操作在教程1里面有, 但是这里也详细的写了每个步骤, 为了方便嘛, 惜墨如金不是什么好习惯...)
把TQ2440测试程序的源码的src和inc复制到一个文件夹下
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708778A2OL6S.png
打开keil软件, project->new uVision Project...
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708779L1ZXUS.png
工程名就定为TQ2440_Test了
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708780T9H93P.png
选择S3C2440...
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708781VI05C2.png
选否, 这回就不用MDK给的启动代码了, 我们是要移植程序, 直接用tq2440_test里的2440init.s嘛,
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708782RJBWY3.png
习惯改下名, 然后添加些文件...
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708783O7VBN6.png
然后看图吧, 没必要详细讲, 自己摸索就会了
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708784MNZ64Y.png
接下来开始设置工程了:
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708785STN3TQ.png
这个好像不必要, 习惯而已
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708786CGEN2R.png

http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708787VQM7P1.png

fromelf.exe --bin -o @p.bin output/@p.axf
关于这个命令的, 我的第一个教程的帖子里传有相关的资料
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708788INOKP7.png

后面的配置比较重要了, 头文件的, 还有uncheck Enable Arm/Thumb interworking
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708792VXW339.png
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708793XWHDK2.png

这个配置也很重要, 移植成功的一个重要配置, 我不太会解释, 因为MDK的链接器感觉本来就不太好用
关于那个sort的, 可以自己去参考MDK的linker的说明文档
我在上面的原理中说到, 要在前面的4K的程序里面完成代码的搬移工作, 这个配置的主要目的就是让nand.c(进行代码搬移的那部分工作的函数就在这个文件里) 生成的目标被安排到前4K的内容, 你也可以尝试自己写分散加载文件, 我试过的比较好的方法就是这样了, 如果你有更好的配置方法, 也希望你能分享你的方法哈./emotion/em012.gif
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708795UVCGXV.png

调试的配置, 如果你不打算用J-LINK调试, 也可以不配置
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708796ZTV80Y.png

还要复制一个初始化文件,文件在Keil的安装目录里找, 我这里是D:\Program Files\Keil\ARM\Boards\Samsung\S3C2440\RTX_Blinky\Ext_RAM.ini
直接复制到你的工程目录下, 然后还要做一点修改, 如果不修改, 就调试不了, 会出现这样的情况
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708798SLXFDT.jpg
工程输出的.axf文件(我也不清楚是用来干啥的)在工程目录下的Output文件夹里, 所以可以用编辑工具(记事本就行了)打开来这样修改:
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708797BF345V.png
最后设置utilities这里添加了烧写算法的, 其实在烧NOR Flash那里我才需要这个, 这个算法是不能擦除的, 但是这里我找不到合适的算法, 就用这个相近的了, 要擦除的话就用JFlash, 你也可以自己写一个算法, 参考MDK的文档, 搜flash programming algorithm之类的字眼, 你会找到的
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708801H68CBK.jpg
到这里, 设置完啦~接下来~要改一点代码...


三. 修改部分代码

(1). 在2440Init.S文件的   
AREA    Init,CODE,READONLY
把Init改成RESET (MDK默认的符号... = =)
然后在这一行后,加入如下行:
PRESERVE8    ;8 字对齐
这样做,主要是为了排除如下错误
.\output\2440test.axf: Error: L6238E: 2440init.o(Init) contains invalid call from '~PRES8' function to 'REQ8'
function Main.
.\output\2440test.axf: Finished: 0 information, 0 warning and 1 error messages.
Target not created


(2). 然后是修改一些名字:

在2440init.s中做如下替换:
(注意: 汇编的格式我并不太懂, 所以原来的代码怎样缩进(空多少格), 你就怎样做, 要不然...出了错也不知道神马原因...)
将如下代码段(75行附近)
IMPORT|Image$$RO$$Base|; Base of ROM code
IMPORT|Image$$RO$$Limit|; End of ROM code (=start of ROM data)
IMPORT|Image$$RW$$Base|   ; Base of RAM to initialise
IMPORT|Image$$ZI$$Base|   ; Base and limit of area
IMPORT|Image$$ZI$$Limit|; to zero initialise
替换为:
IMPORT|Image$$ER_ROM1$$RO$$Base|   ; Base of ROM code
IMPORT|Image$$ER_ROM1$$RO$$Limit|; End of ROM code (=start of ROM data)
IMPORT|Image$$RW_RAM1$$RW$$Base|   ; Base of RAM to initialise
IMPORT|Image$$RW_RAM1$$ZI$$Base|   ; Base and limit of area
IMPORT|Image$$RW_RAM1$$ZI$$Limit|; to zero initialise

将450 行附近
BaseOfROMDCD|Image$$RO$$Base|
TopOfROMDCD|Image$$RO$$Limit|
BaseOfBSSDCD|Image$$RW$$Base|
BaseOfZeroDCD|Image$$ZI$$Base|
EndOfBSSDCD|Image$$ZI$$Limit|
替换为:
BaseOfROMDCD|Image$$ER_ROM1$$RO$$Base|
TopOfROMDCD|Image$$ER_ROM1$$RO$$Limit|
BaseOfBSSDCD|Image$$RW_RAM1$$RW$$Base|
BaseOfZeroDCD|Image$$RW_RAM1$$ZI$$Base|
EndOfBSSDCD|Image$$RW_RAM1$$ZI$$Limit|

将Main.c中的如下段(18-23行)
extern char Image$$RO$$Limit[];
extern char Image$$RO$$Base[];
extern char Image$$RW$$Limit[];
extern char Image$$RW$$Base[];
extern char Image$$ZI$$Limit[];
extern char Image$$ZI$$Base[];
替换为:
extern char Image$$ER_ROM1$$RO$$Limit[];
extern char Image$$ER_ROM1$$RO$$Base[];
extern char Image$$RW_RAM1$$RW$$Limit[];
extern char Image$$RW_RAM1$$RW$$Base[];
extern char Image$$RW_RAM1$$ZI$$Limit[];
extern char Image$$RW_RAM1$$ZI$$Base[];

将如下代码(67 行前后)
extern char Image$$RW$$Limit[];
U32 *pMagicNum=(U32 *)Image$$RW$$Limit;
替换为:
extern char Image$$RW_RAM1$$RW$$Limit[];
U32 *pMagicNum=(U32 *)Image$$RW_RAM1$$RW$$Limit;

将2440Lib.c中的如下代码(19-20 行)
extern char Image$$RW$$Limit[];
void *mallocPt=Image$$RW$$Limit;
替换为:
extern char Image$$RW_RAM1$$RW$$Limit[];
void *mallocPt=Image$$RW_RAM1$$RW$$Limit;

LCD_TFT.h第14行: 我的开发板配的是4.3寸的,
#define LCD_Type                LCDW43                //设定屏的类型

呼...终于改完了...哥又截图又改代码快累死了...
编译, 生成的bin文件就可以下载到nand flash去了, 下载的方式和TQ2440裸奔教程上说的一样
如果你想用JLINK烧到nor flash
可以这样http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708802FU4QOY.png
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708803N4ZPQF.png
看, 变了
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708804WNX96M.png
然后你可以很方便的重新配置
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708807MYZ3KY.png
因为utilities那部分刚才已经配置了, 所以现在改一下地址就行了
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708808AM6PNN.png
编译, 然后就可以用J-LINK烧到NOR flash里去了 ^_^
(烧写之前要先擦除的哟...哥已经不想再截图了...参考教程1的内容去)
两种配置可以很方便的切换的^_^
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708809GNU4LE.png



四. 测试结果
    关于NOR烧写的, 可能程序比较大, 然后算法不合适, 我这里刚刚测试没成功过, 总是会有TIME OUT之类的信息...
    RAM调试的基本通过, 但是按键中断测试出了点问题, 这个我也不太清楚, 以后再研究吧~
    下载到NAND的测试通过了, 没发现问题, 所以我的目的已经达到了~
http://cache.amobbs.com/bbs_upload782111/files_49/ourdev_708810DK0RMX.png

haohan007 发表于 2011-12-29 19:55:55

哇,又见Pony279了,你辛苦了。我顶。

Pony279 发表于 2011-12-29 20:16:14

回复【4楼】haohan007
-----------------------------------------------------------------------

谢谢./emotion/em012.gif

tyqhaha 发表于 2011-12-29 20:38:44

mark下 最近在搞430 有机会再看~

LK9286 发表于 2011-12-30 17:17:38

MARK

hyz_avr 发表于 2011-12-30 17:21:49

顶一下.

416446891 发表于 2011-12-30 19:49:30

MARK

ChengBing 发表于 2011-12-30 19:58:34

保存了

0season0 发表于 2011-12-30 20:18:21

顶下,牛x的说犀利

painberg 发表于 2012-2-2 00:36:37

开始没找到代码哈!

Pony279 发表于 2012-2-11 17:53:33

更正:有网友指出,文档中这一部分是错误的,ARM9是哈佛结构的,不好意思

“2440算是冯诺什么曼结构的计算机, 通俗的说, 2440的程序代码是可以放在RAM里面执行(我们的PC机也是这种类型的), 不同于51, 也许你会注意到, 51的程序是不能在内部的RAM里面执行的, 现在的51单片机的程序一般是存在片内的ROM里的, 传统的51的内部RAM顶多也就那么256个字节, 变量都存不了几个, 运行个鬼程序, 51单片机算是哈佛结构的.”

avrwoo 发表于 2012-2-11 19:27:30

mark

ou513 发表于 2012-2-13 15:10:16

这个我喜欢啊,太好了

zhouxin_1985 发表于 2012-2-13 15:28:32

很详细,非常好!

avrwoo 发表于 2012-2-14 09:55:44

MARK

it1988 发表于 2012-2-23 16:18:07

楼主辛苦。
我来Mark 一下。

ky51 发表于 2012-4-17 09:29:25

coolljt 发表于 2012-4-17 09:50:09

挺喜欢用KEIL的,就是keil没有结构体自动提示功能,有时很不方便

dianzichina 发表于 2012-4-20 09:46:26

楼主的讲解很详细很细致啊,那么多的过程你都能记得这得清楚。一个字,牛。

itfan 发表于 2012-4-20 10:30:54

谢谢楼主啊!!!

无限幻想 发表于 2012-4-28 15:06:15

makddddddd

keshipt 发表于 2012-6-7 12:27:15

很好 顶顶顶

xiaozi0221 发表于 2012-6-7 15:34:44

楼主很辛苦,这样认真还是要顶一下的

ky51 发表于 2012-6-9 19:18:15

hnust_mcu 发表于 2012-7-10 23:25:47

谢谢,入门强帖。

ananlaiye 发表于 2012-8-12 01:23:35

{:lol:}哥,你辛苦了~~~~

a105 发表于 2012-10-19 15:59:41

对初学者很有帮助呀

BigSea001 发表于 2012-11-14 09:22:19

朋友送的板子,试着玩玩,感谢lz

panda1985 发表于 2012-11-14 18:42:09

mark            

wangzheyu 发表于 2012-12-30 17:51:25

感觉楼主这样做还是有问题,因为初始化代码的执行地址其实是一开始的0-4k空间内,但是链接地址都是在sdram中,这样的话,必须是保证所有的跳转指令都是与位置无关的相对跳转指令才行

torpedoyulei 发表于 2012-12-31 15:17:56

我是新手,前几天有点小问题没想通,正好在楼主的贴子里问一下吧,我在qq2440上学习的arm ,之前试着看教程把u_boot移植到了nand 上了,之后就一直用u_boot的网络下载到ram上运行,在配置keil MDK工程的内存分配时每次都要把ROM的地址写为从0x30000000 开始,请问这个地址是运行地址吗?我有点乱了!如果说这个不是运行地址,那么在内存上加载的地址应该是哪?为什么我把程序下载到这个0x30000000上也可以运行?

wangzheyu 发表于 2012-12-31 15:38:13

torpedoyulei 发表于 2012-12-31 15:17 static/image/common/back.gif
我是新手,前几天有点小问题没想通,正好在楼主的贴子里问一下吧,我在qq2440上学习的arm ,之前试着看教程 ...

0x30000000是sdram的地址,你用uboot下载到这个地址的话,就是直接在sdram上运行了的意思,所以在mdk中就是写0x30000000,作为运行地址,而你看一下keil的sct file,默认情况下,加载地址和运行地址是一样的,如果要实现从nand加载到sdram,就要自己写分散加载文件

torpedoyulei 发表于 2012-12-31 15:49:13

wangzheyu 发表于 2012-12-31 15:38 static/image/common/back.gif
0x30000000是sdram的地址,你用uboot下载到这个地址的话,就是直接在sdram上运行了的意思,所以在mdk中就 ...

哦,你的一个词一下让我全想通了,这里是分加载地址和动行地址,如果我没猜错的话是不是加载地址就是程序没运行时的在FLASH中的地址?可是我在移植UBOOT时前4K的文件为什么可以在FALSH上运行,也可以在内存上运行,难到这就是传说中的地址无关代码?

wangzheyu 发表于 2012-12-31 17:14:12

torpedoyulei 发表于 2012-12-31 15:49 static/image/common/back.gif
哦,你的一个词一下让我全想通了,这里是分加载地址和动行地址,如果我没猜错的话是不是加载地址就是程序 ...

额。。对的,都是可以指定的,加载地址和运行地址,一般bootloader的汇编部分会用地址无关的跳转指令

J.H.Chen 发表于 2013-1-1 09:15:02

楼主有6410的吗?

wangjiawu187 发表于 2013-8-5 10:48:24

mark!!!

xiefy21 发表于 2013-8-13 23:01:24

mark……
顶一个…

eliefly 发表于 2013-9-13 14:55:35

谢谢楼主,辛苦!

eliefly 发表于 2013-9-13 16:53:56

D:\Program Files\Keil\ARM\Boards\Samsung
没有S3C2440怎么回事?

harryxp 发表于 2013-10-20 10:42:57

Pony279 发表于 2011-12-29 19:03 static/image/common/back.gif
今天有闲情了, 把内容贴上来

主要内容:


太感谢楼主啦!MARK!
请教2个问题:
1.哪个步骤是修改NANDFLASH的开始地址的?
2.最后为什么要替换一些代码,原因是什么?
页: [1]
查看完整版本: 用Keil MDK开发TQ2440裸机程序入门教程2(移植TQ2440测试程序)