注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

心情挺好的博客

正在等你光临呢 呵呵

 
 
 

日志

 
 
关于我

喜欢摄影的朋友看过来:) 有时间就跟我一起去拍照去吧. QQ272751 上海圣玛丽摄影化妆培训学校 16年专业摄影培训化妆培训学校 电话:15900513500。 http://www.smlsh.com

网易考拉推荐

2009年1月14日  

2009-01-14 14:36:15|  分类: 技术 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

用JTAG接口去刷firmware,详细参见:

http://wiki.openwrt.org/JTAG_Cables

http://wiki.openwrt.org/OpenWrtDocs/...c0c4ea93ffbadd

 

 

 

 

发表于 2008-9-8 18:53:14
常见的JTAG cable结构都比较简单,一端是DB25,接到电脑的并口上,中间经过74HC244和一些电阻实现电平转换(5V3.3V?)(也有比较猥琐的只用了 几个100 Ohm电阻的方案),另一端的JTAG header接到目标板的JTAG interface。
并口DB25原先主要是用来连接打印机,其引脚定义如下:
25 Pin D-Sub SPP SIGNAL DIRECTION IN/OUT
1            /Strobe               In/Out
2            Data 0                Out
3            Data 1                Out
4            Data 2                Out
5            Data 3                Out
6            Data 4                Out
7            Data 5                Out
8            Data 6                Out
9            Data 7                Out
10          /ACK                   In
11         Busy                    In
12         Paper Out           In
13         Select                  In
14         /Line Feed          In/Out
15         /Error                   In
16         /INIT                     In/Out
17         /Select In             In/Out
18-25   Ground GND
可见,数据线Pin2~Pin9可以用来发送数据,Pin10~Pin13等可以用来接收数据。
JTAG的数据传输形式是串行,主要使用了以下引脚:
TDI (Test Data In)
TDO (Test Data Out)
TCK (Test ClocK)
TMS (Test Mode Select)
TRST (Test ReSeT) optional.
因此,DB25-JTAG实际上只利用了DB25的少数几根线。但由于DB25的8条数据线都可以作为output,市面上就出现了各种使用不同Pin Assignment的JTAG线。

例如Wiggler的Pin assignment:
TMS : Pin3 (D1)
TCK : Pin4 (D2)
TDI : Pin5 (D3)
TDO : Pin11 (Busy)
SRST   : Pin2 (D0)
TRST   : Pin6 (D4)
(参见Wiggler的电路图,但最后的nSRST和nTRST可能不一定用到,并且在H-JTAG中的定义也不一样,TRST是Pin2,没有SRST)
H-JTAG里还有另外一种接法--STD,定义如下:
TMS : Pin3 (D1)
TCK : Pin2 (D0)
TDI : Pin8 (D6)
TDO : Pin13 (Select)
SRST   : N/A
TRST   : Pin4 (D2)
而S3C2410的烧写程序SJF2410用的是:
TCK : Pin2 (D0)
TDI : Pin3 (D1)
TMS : Pin4 (D2)
TDO : Pin11 (Busy)
这个可以在源代码中的jtag.h文件里看到。
除了DB25那边的Pin Assignment有多种方案,JTAG connector也有20pin, 14pin, 12pin, 10pin等几种标准。这里一块ARM9开发板配的DB25-JTAG转换板就十分好玩,上面也是只有一块244,但是有Wiggler, STD, S3C2410三个20pin接口。由于20pin connector的Pin Assignment是固定的,三个接口对应的是DB25那边的三种接法,因此开发板可以根据pc上运行的程序不同选择不同的接口来接。
20Pin Connector的定义如下(参考此图):
Vcc         ← 1     2  →   NC
nTRST   ← 3     4  →   GND
TDI          ←5     6  →   GND
TMS        ←7     8  →  GND
TCK        ←9    10 →  GND
GND     ←11    12 →  GND
TDO     ←13     14 → GND
NRESET   ←15    16 → GND
NC       ←17     18  → GND
NC       ←19     20  →  GND
14Pin:
nTRST  ← 1    2 →  GND
TDI        ← 3    4 → GND
TDO      ← 5    6 →  GND
TMS       ←7    8 → GND
TCK       ←9   10 → GND
nSRST ←11  12 →  n/a
DINT    ←13   14 → Vcc
(DINT pin is used to raise Debug Interrupt. Many chips has no this pin.)
12Pin:
nTRST  ← 1    2 → GND
TDI        ← 3    4 → GND
TDO      ← 5    6 → GND
TMS      ← 7    8 → GND
TCK      ← 9   10 → GND
nSRST ←11   12 → GND
10Pin:
TCK      ← 1     2 → Vcc
TDI       ← 3      4 → Vcc
TDO     ← 5      6 → GND
TMS     ← 7      8 → GND
nTRST← 9      10 → GND
关于JTAG几个信号,在H-JTAG主页上提供了一个文档,里面有对此进行介绍:

  
……下面,让我们从TAP(Test Access Port)开始。
  TAP是一个通用的端口,通过TAP可以访问芯片提供的所有数据寄存器(DR)和指令寄存器(IR)。对整个TAP的控制是通过TAP Controller来完成的。TAP总共包括5个信号接口TCK、TMS、TDI、TDO和TRST :其中4个是输入信号接口和另外1个是输出信号接口。一般,我们见到的开发板上都有一个JTAG接口,该JTAG接口的主要信号接口就是这5个。下面,我 先分别介绍这个5个接口信号及其作用。
Test Clock Input (TCK)
TCK为TAP的操作提供了一个独立的、基本的时钟信号,TAP的所有操作都是通过这个时钟信号来驱动的。TCK在IEEE 1149.1标准里是强制要求的。
Test Mode Selection Input (TMS)
TMS信号用来控制TAP状态机的转换。通过TMS信号,可以控制TAP在不同的状态间相互转换。TMS信号在TCK的上升沿有效。TMS在IEEE 1149.1标准里是强制要求的。
Test Data Input (TDI)
TDI是数据输入的接口。所有要输入到特定寄存器的数据都是通过TDI接口一位一位串行输入的(由TCK驱动)。TDI在IEEE 1149.1标准里是强制要求的。
Test Data Output (TDO)
TDO是数据输出的接口。所有要从特定的寄存器中输出的数据都是通过TDO接口一位一位串行输出的(由TCK驱动)。TDO在IEEE 1149.1标准里是强制要求的。
Test Reset Input (TRST)
TRST可以用来对TAP Controller进行复位(初始化)。不过这个信号接口在IEEE 1149.1标准里是可选的,并不是强制要求的。因为通过TMS也可以对TAP Controller进行复位(初始化)。
  事实上,通过TAP接口,对数据寄存器(DR)进行访问的一般过程是:
  1 通过指令寄存器(IR),选定一个需要访问的数据寄存器;
  2 把选定的数据寄存器连接到TDI和TDO之间;
  3 由TCK驱动,通过TDI,把需要的数据输入到选定的数据寄存器当中去;同时把选定的数据寄存器中的数据通过TDO读出来。
另外,可选信号nSRST的定义如下(见参考资料1):
nSRST is a "system reset" signal and acts like conventional "Reset' button.
参考资料:
[1] http://www.linux-mips.org/wiki/JTAG
[2] http://en.wikipedia.org/wiki/Jtag
[3] http://docwiki.gumstix.org/JTAG
[4] http://wiki.openwrt.org/OpenWrtDocs/Customizing/Hardware/JTAG_Cable
[5] http://www.bluewaternz.com/corporate/uni/unikit/jtag/
从这里明白了市场上各个板子公司的jtag接口为何有20pin, 10pin,12pin,14pin的原因。再阅读了高手
litron 的文档,http://blog.chinaunix.net/u/23070/showart.php?id=157735
把jtag.h文件改动了一下
// Pin Connections
// TCK :DATA[0] (2) // my is 4   DATA[2]
// TDI :DATA[1] (3) // my is 5   DATA[3]
// TMS :DATA[2] (4)   //my is 3 DATA[1]
// TDO :STATUS[7] (11)
//#define TCK_H        0x01
#define TCK_H        0x04
//#define TDI_H        0x02             
#define TDI_H        0x08             
//#define TMS_H        0x04
#define TMS_H        0x02
编译,烧写,
[root@hujunlinux Jflash]# ./Jflash-s3c2410   vivi   /t=5

+------------------------------------+
|     SEC JTAG FLASH(SJF) v 0.11     +
|     modified by MIZI 2002.7.13     +
+------------------------------------+
> flashType="5"
> S3C2410X(ID=0x0032409d) is detected.
> K9S1208 is detected. ID="0xec76"

K9S1208 NAND Flash JTAG Programmer Ver 0.0
0:K9S1208 Program    1:K9S1208 Pr BlkPage 2: Exit

Select the function to test :0

[SMC(K9S1208) NAND Flash Writing Program]

Source size: 0x13a53

Available target block number: 0~4095
Input target block number:0
target start block number     =0
target size        (0x4000*n) =0x14000
STATUS:Epppppppppppppppppppppppppppppppp
Epppppppppppppppppppppppppppppppp
Epppppppppppppppppppppppppppppppp
Epppppppppppppppppppppppppppppppp
Epppppppppppppppppppppppppppppppp

K9S1208 NAND Flash JTAG Programmer Ver 0.0
0:K9S1208 Program    1:K9S1208 Pr BlkPage 2: Exit

Select the function to test :2
jflash 可以烧写了,但是把vivi烧进去之后,运行minicom,串口没有输出,但是在windows下用
sjf2410烧写同样的一个vivi,正常运行,
碰到这个问题是因为我烧写vivi之后,
没有关闭电源,再打开板子, 只是按了一下板子上的Reset按钮,重新关闭再打开,串口就看到了vivi的启动信息。
这里提供我的Jflash源代码,
说明适合采用wiggler的jtag ,
// TCK :DATA[0] (2) // my is 4   DATA[2]
// TDI :DATA[1] (3) // my is 5   DATA[3]
// TMS :DATA[2] (4)   //my is 3 DATA[1]
意思是TCK->pin4,也就是DATA[2],应为pin2-pin9组成了DATA,所以pin2就是DATA[0]
依次类推TDI,TMS。TDO采用的是pin11, 因为我的jtag的TDO跟litron大侠采用的是一样的,
pin11,就没管它了。

系统分类: 软件开发
用户分类: LINUX
标签: 无标签
来源: 转贴
发表评论 阅读全文(445) | 回复(0)

1

2009年1月14日 - 心情挺好 - 心情挺好的博客
发表于 2008-9-8 18:33:51

 

作者:小布

学习ARMJTAG这一关是必须要过的。但是似乎对应于不同的调试软件有不同的电路,又有可否烧写flash之分。这对初学者未免造成一些困惑,其实这层窗纸太薄了,一点即透。

我们首先来看Jtag几条线的作用:

??Test Clock Input (TCK)

TCKTAP的操作提供了一个独立的、基本的时钟信号,TAP的所有操作都是通过这个时钟信号来驱动的。TCKIEEE 1149.1标准里是强制要求的。

??Test Mode Selection Input (TMS)

TMS信号用来控制TAP状态机的转换。通过TMS信号,可以控制TAP在不同的状态间相互转换。TMS信号在TCK的上升沿有效。TMSIEEE 1149.1标准里是强制要求的。

??Test Data Input (TDI)

TDI是数据输入的接口。所有要输入到特定寄存器的数据都是通过TDI接口一位一位串行输入的(由TCK驱动)。TDIIEEE 1149.1标准里是强制要求的。

??Test Data Output (TDO)

TDO是数据输出的接口。所有要从特定的寄存器中输出的数据都是通过TDO接口一位一位串行输出的(由TCK驱动)。TDOIEEE 1149.1标准里是强制要求的。

??Test Reset Input (TRST)

TRST可以用来对TAP Controller进行复位(初始化)。不过这个信号接口在IEEE 1149.1标准里是可选的,并不是强制要求的。因为通过TMS也可以对TAP Controll进行复位(初始化)。--所以有四线JTAG与五线JTAG之分。

其实对JTAG来说有着几根线就够了,再算上电源和地最多才7根线啊,可常见的接口方式是20针的插座啊;多出来的几根线适用于高级一点的用途,对于新手来说是不需要的。

??(VTREF)

接口信号电平参考电压一般直接连接Vsupply。这个可以用来确定ARMJTAG接口使用的逻辑电平(比如3.3V还是5.0V?

??Return Test Clock ( RTCK)

可选项,由目标端反馈给仿真器的时钟信号,用来同步TCK信号的产生,不使用时直接接地

??System Reset ( nSRST)

可选项,与目标板上的系统复位信号相连,可以直接对目标系统复位。同时可以检测目标系统的复位情况,为了防止误触发应在目标端加上适当的上拉电阻。

??USER IN

用户自定义输入。可以接到一个IO上,用来接受上位机的控制。

??USER OUT

用户自定义输出。可以接到一个IO上,用来向上位机的反馈一个状态

由于JTAG经常使用排线连接,为了增强抗干扰能力,在每条信号线间加上地线就出现了这种20针的接口。但事实上,RTCKUSER INUSER OUT一般都不使用,于是还有一种14针的接口。对于实际开发应用来说,由于实验室电源稳定,电磁环境较好,干扰不大,使用那么多地线意义不大,个人使用一种10针接口,接口方式与AVRJTAG接口顺序相近(非标准,不推荐大家使用)。下面是接口示意:

按照个人理解:JTAG开发工具有:USB Multi-ICE、并口Multi-ICE、简易JTAG.,价格由高到低,速度由快而慢,功能由强而弱。JTAG作为一种嵌入式系统调试规范,是有一套协议的,并口Multi-ICE就是将计算机对并口的读写转为JTAG协议,其实大家如果拆开看过,就很容易理解了,主要部分是一片FPGA,程序在EEPROM里。大家知道价格为啥差那么多了吗?成本低,进入门槛低,会抄板就行了。USB的只不过是多了一层USB协议,由于USB本身较并口为快,所以速度要快一些。不要问我有多快,我没用过。简易JTAG只有一片74HC244,其实是用并口模拟JTAG协议,由于JTAG是串行协议(废话,那么几根线怎么并行),所以并口的n次操作才能完成一条命令(n>8),事实上是远大于8,能快起来才怪呢。单片机的并口ISP下载是同样的道理(如果ISP最高速度受限那就不好说了)。

不要问我简易JTAG是不是具有Multi-ICE的全部功能,原则上是可以具有的。但是软件支持不支持就得另说了。就好像我们花钱买开发板一样,其实买的是一个售后服务。

网上有个很牛的仁兄,用一片EPM3128和一片Atmega8自己设计了一个Multi-ICE,并共享了一些资料,大家可以照着做一下。资料下载用google搜。

终于说到简易JTAG了,下面先看几张原理图:

第一张:支持软件SJF2410.exe,是三星提供的2410 flash烧写软件。2410开发的话最好备一个。

第二张:是JTAG for ARM SDT

第三张:是一家公司的Wiggler for X-JTAG原理图。

第四张:是另外一家公司提供的JTAG原理图。

第五张:是另一个版本的Wiggler

贴图不太全,其实没多大意思,主要区别是几条线对应的并口线序不同,反映到ARM那里都是一样的。最好的解决办法就是用一片PLD,对应什么软件就使用什么样的连接顺序,可以接几个跳线作为输入,免得每次更改程序。太大材小用了吧?不然,以后调试单片机、CPLD都可以用啊。现在有一种万能下载线就是这么做的。什么?不会用CPLD?那就用模拟开关设计一个电路出来,或者下面图每样做一个也行,做PCB的时候拼版,用不了几个钱。

 

      友情提示一下,有些公司为了显示自己的技术能力,把接口改的乱七八糟,跟谁的都不兼容,这时候就买他一根下载线好了。没几个钱,别耽误了项目。

      一个简易的JTAG究竟工作是否正常,除了可以用相应软件调试外,推荐大家使用X-JTAG调试,关于X-JTAG的使用参见好友NOCKY的《在ADS中使用XJTG》。

系统分类: 软件开发
用户分类: LINUX
标签: 无标签
来源: 转贴
发表评论 阅读全文(283) | 回复(0)

1

2009年1月14日 - 心情挺好 - 心情挺好的博客
发表于 2008-9-6 11:52:49

文章引自:http://piaoxiang.cublog.cn

现在基本熟悉了

GNU asldobjdumpobjcopy。可以进行后续的基本实验了。今天把s3c2410memory controller看了,结合《s3c2410完全开发》实验五,实现了一个sdram的简单实验。源代码如下,下面重点分析s3c2410复位后的内存映射,及其应用。

 

一、基本配置

    EDUKIT-III采用核心子板加扩展板的设计方式,我学习ARM9,所以采用s3c2410的核心子板。核心子板资源如下:

 

    MCU      S3C2410A

    SDRAM    两片HY57V561620CT-H

    NOR FLASH AM29LV160DB-90EC

 

    扩展板资源:

 

    NAND FLASH K9F5608UOC

 

二、nand flash boot分析

 

    S3C2410支持从nor/nand flasheepromrom类型的介质启动。现在我想做的是从外部nand flash启动,首先看datasheet第一部分:

NAND Flash Boot Loader
· Supports booting from NAND flash memory
· 4KB internal buffer for booting
· Supports storage memory for NAND flash memory after booting

NAND Flash Boot Loader
· Supports booting from NAND flash memory
· 4KB internal buffer for booting
· Supports storage memory for NAND flash memory after booting

 

    可以明确,首先,s3c2410支持从nand flash存储介质启动,其次,在硬件上,s3c2410除了提供相应的逻辑外,还提供了一个4Ksram作为buffer用于nand启动。最后,s3c2410支持从nand flash启动之后的内存分配形式(也就是说,从nand flash启动之后和从nor flash启动之后的内存分配形式是不同的。s3c2410支持这两种形式,可以说是相对于其他的MCU不同的地方。)

 

    然后看datasheet的第六部分:nand flash controlleroverview中首先讲述了用nand flash代替nor flash作为启动介质的原因(成本低)。

 

    S3C2410X boot code can be executed on an external NAND flash memory. In order to support NAND flash boot loader, the S3C2410X is equipped with an internal SRAM buffer called ‘Steppingstone’. When booting, the first 4
KBytes of the NAND flash memory will be loaded into Steppingstone and the boot code loaded into Steppingstone will be executed.
    Generally, the boot code will copy NAND flash content to SDRAM. Using hardware ECC, the NAND flash data validity will be checked. Upon the completion of the copy, the main program will be executed on the SDRAM.

 

    可以很明显的看出,s3c2410x启动代码从外部nand flash启动的流程:上电复位后,s3c2410自动读取nand flash的前4KBytes的数据到内部sram buffer中,这个硬件的sram buffer被称为“Steppingstone”。然后执行下载到steppingstone的代码,这部分代码完成将nand flash的内容复制到sdram中,在复制时,利用硬件的ECC验证数据有效性。完成复制后,主程序就开始从sdram执行。

 

    过程应该是很清晰。但是首先怀疑的是,s3c2410如何实现自动读取nand flash的前4KBytes数据到内部sram buffer当中。网上为什么没人就这点产生疑问,并深入分析呢?我分析可能有两种方法:一是像at91rm9200一样,内部集成一个小的rom,固化代码,这部分代码的作用就是完成自动读取功能;二是完全用硬件实现。仔细看了框图,发现s3c2410只有internal sram buffer,并没有rom,所以最大可能就是硬件实现。看一下硬件框图figure6-1,可以发现hardware ECC编解码器,可以看到internal buffer4KB),另外注意的一个地方是,存在着control state machinebuffer control,而且之间有粗体线链接。也就是说明了用一个控制状态机实现了自动读取4KB数据的过程,完全的硬件实现。如下图所示:

 

    明确了这个问题之后,对从硬件上电到nand flash启动就比较清晰了。而且,也就理解为什么vivistage1head.S必须要小于4KB,因为internal sram buffer只有4KB。如果要完成一个比较复杂的bootloader,那也应该尽量简化stage1,完成基本的初始化之后,把剩余的工作量都放到将nand flash的代码搬移到sdram之后进行。

 

memory controller分析

 

    datasheet第五部分。s3c2410比较特殊,支持1G的内存空间,分为8bank,每个bank128MBytes128MB×81GB。但是在这8bank中,又有所不同,并且nand flash不对应任何bank,它是通过一组寄存器来访问的,可看上面框图的register bank

 

— Total 8 memory banks
   Six memory banks for ROM, SRAM, etc.
   Remaining two memory banks for ROM, SRAM, SDRAM, etc .
— Seven fixed memory bank start address
— One flexible memory bank start address and programmable bank size

 

    可以推断出,sdram应该在bank6,起始地址固定为128M*60x30000000,在此之后,就要根据sdram的大小和位宽来决定了,而且有个注意的地方是,bank7必须和bank6一样大小。参考figure5-1table 5-1就非常清晰了。现在EDUKIT-III上用了两片SDRAM,型号是HY57V561620CT-H,查看datasheet,它是4banks×4M×16bit256Mbits32Mbytes,那么两片组合起来就是64MBytes,位宽是32bit,所以bank6的地址范围是[0x30000000-0x33ffffff]bank7的地址范围是[0x34000000-0x37ffffff]。查看s3c2410 table 5-2,可以知道bank选择地址线为A[25:24]--->BA[1:0]

 

    关于sdram,还应该知道刷新频率和列宽度。HY57V561620CT-H datasheet中,有:

 

· Auto refresh and self refresh
· 8192 refresh cycles / 64ms
· Programmable Burst Length and Burst Type
  - 1, 2, 4, 8 or Full page for Sequential Burst
  - 1, 2, 4 or 8 for Interleave Burst
· Programmable CAS Latency ; 2, 3 Clocks

 

    所以刷新频率为64ms/81927.8125us

 

    查看PIN DESCRIPTION,可以看出A0-A12为地址,其中ROW AddressRA[0:12]Column AddressCA[0-8],显然CAS的位数为9bits

 

四、实验内容分析

 

    实验内容很简单,就是完成基本的初始化之后,把steppingstone4K数据搬移到sdram中。然后在sdram中执行灯循环点亮程序。结合这个实验,也可以很清晰的明白,前面几个基本实验,从nand flash启动后,所有代码只是搬移到了steppingstone中,也就是实际执行时是在steppingstone中,也就是boot internal sram4KB)中执行的,所以运行时域和加载时域都是0x00000000,设置的堆栈可以是1024,也可以是4096,但是注意一是最大为4096,二是保证不与可执行代码发生冲突。在这个程序中,运行时域和加载时域是不相同的。加载时域是0x00000000,但是运行时域是0x30000000。《s3c2410完全开发》对这个地方讲解不是太详细。经过实验,和王老师的帮助,弄清楚了到底怎么回事。现在关于运行时域和加载时域的具体分析如下:

 

    根据nand flash的特点,初始代码的加载时域为0x00000000,也就是当前PC的值为0x00000000,两种跳转指令b(l)等只能相对寻址,最大范围是+/-32MBytes,所以如果不改变PC的话,不可能能利用b或者bl跳转到sdram的空间中。跳转指令ldr则不受此寻址空间的限制,可以进行绝对寻址。需要了解的一个细节就是,链接后所有的标号都是基于运行地址的,比如运行地址为0x30000000,那么第一个标号_start地址就是0x30000000,所以可以利用ldr的绝对寻址来完成到sdram的跳转。下面根据编写的sdram的反汇编来进行分析:

 

    首先看在不去除符号信息的前提下:

 

sdram: $(OBJS)
        $(LD) $(LDFLAGS) $^ -o $@.o
        $(OBJDUMP) -D $@.o >$@_s
        $(OBJCOPY) -O binary -S $@.o $@

 

    这里是反汇编的结果:

 

Disassembly of section .text:

30000000 <_start>:
30000000:       e3a00453        mov     r0, #1392508928 ; 0x53000000
30000004:       e3a01000        mov     r1, #0  ; 0x0
30000008:       e5801000        str     r1, [r0]
3000000c:       eb00000c        bl      30000044 <memsetup>
30000010:       eb000003        bl      30000024 <copy_steppingston_to_sdram>
30000014:       e59ff088        ldr     pc, [pc, #88]   ; 300000a4 <mem_cfg_val+0x34>

30000018 <setup_stack>:
30000018:       e3a0d30d        mov     sp, #872415232  ; 0x34000000
3000001c:       eb000023        bl      300000b0 <main>

30000020 <stop>:
30000020:       eafffffe        b       30000020 <stop>

 

    可以很明显的看出,_start0x30000000stop0x30000020。也就是说,经过链接之后,symbol table中的存放位置都是基于运行起始地址0x30000000的。但是需要注意的是,开始运行是PC的值为0x00000000,虽然bl 30000040 <memsetup>30000040,但是要注意,此处指令为bl,所以只能相对寻址,而不能够绝对寻址,也就是说,它只能跳转到距离0x300000000x40的位置,这点查看bl的汇编指令说明就比较清晰了。

 

        ldr pc, =setup_stack
setup_stack:
        ldr sp, =stack_top
        bl main

 

    利用上面的技巧,就可以把PC的值装载到sdram的空间,因为之前代码搬移已经完成了,所以,后续的工作都已经工作在sdram的空间中了。

 

    如果在利用objcopy去除了符号信息之后,反汇编之后的结果只能是以0开始的相对地址,也就看不出上面的东西了,所以,要理解还应该是采用上面的分析方法。这点在《s3c2410完全开发》上是没有详细说明的。写到这里,自己已经比较清晰了。关于其他的分析,《s3c2410完全开发》已经比较详细了,可以参考。

 

    程序源代码如下:

 

文件:

sdram.tar.gz

大小:

2KB

下载:

下载

链接:作者的“ vivi开发笔记【专辑】

系统分类: 软件开发
用户分类: LINUX
标签: 无标签
来源: 转贴
发表评论 阅读全文(212) | 回复(0)

1

2009年1月14日 - 心情挺好 - 心情挺好的博客
发表于 2008-9-6 11:47:12

  http://blog.csdn.net/aganpro/archive/2006/09/21/1258595.aspx

  这几天一直在摸索s3c2410的启动过程,几天的困惑终于在昨天晚上基本解决.下面详细分析一下它的最前面的启动过程.

       1.在板子上电的一开始,首先自动判断是否是autoboot模式(这是由硬件设计阶段,由硬件工程师对mcu的引脚连线决定的),我所使用的s3c2410是带有nandflash的,并切被设置成autoboot,从nandflash开始启动. 

      2.在判断是autoboot模式后,mcu内置的nandflash控制器自动将nandflash的最前面的4k区域(这4k区域存放着bootloader的最前面4k代码)拷贝到samsung所谓的"steppingstone"里面(实际上是一块4k大小的SRAM).

      3.在拷贝完前4k代码后,nandflash控制器自动将"steppingstone"映射到arm地址空间0x00000000开始的前4k区域.

      4.在映射过程完成后.nandflash控制器将pc指针直接指向arm地址空间的0x00000000位置,准备开始执行"steppingstone"上的代码.

      5.而"steppingstone"上从nandflash拷贝过来的4k代码,是程序员写的bootloader的前4k代码.这个bootloader在之前写好,并已经被烧写到nandflash的0x00000000开始的最前面区域..而这"steppingstone"上的4k代码就是bootloader的前4k代码.

      6.在pc指向arm地址空间的0x00000000后,系统就开始执行指令代码.这4k代码的任务是:初始化硬件,设置中断向量表,设置堆栈,然后一个很重要的任务是,将nandflash的最前面区域的bootloader(包含4k启动代码)拷贝到SDRAM中去,bootloader代码的大小是写好bootloader就确定的.然后只需要确定bootloader想映射到SDRAM的起始位置就ok.

      7.在完成对nandflash上的bootloader搬移后,找到4k代码的搬移代码最后一个指令的下一个指令在SDRAM的bootloader的地址,然后跳转到该位置,继续执行bootloader的剩余代码(引导系统).

 

       目前还有不清楚或含混的地方就是中断向量表的具体设置,好象要经过几个跳转,这里比较含混.还有就是SDRAM在arm地址空间位置的确定,这个搞清是很必要的.以上就是这几天搞的事情.

系统分类: 软件开发
用户分类: LINUX
标签: 无标签
来源: 转贴
发表评论 阅读全文(171) | 回复(0)

2

2009年1月14日 - 心情挺好 - 心情挺好的博客
发表于 2008-9-6 0:40:11
第7540篇:U-Boot在S3C2410上的移植(具体URL忘了,我文章是下载的,知道的朋友告诉一声)
一、整体结构
首先下载u-boot的源代码(www.denx.de),解压缩,你可以看到下面的目录:
- board 目标板相关文件,主要包含SDRAM、FLASH驱动;
- common 独立于处理器体系结构的通用代码,如内存大小探测与故障检测;
- cpu 与处理器相关的文件。如mpc8xx子目录下含串口、网口、LCD驱动及中断初始化等文件;
- driver 通用设备驱动,如CFI FLASH驱动(目前对INTEL FLASH支持较好)
- doc U-Boot的说明文档;
- examples可在U-Boot下运行的示例程序;如hello_world.c,timer.c;
- include U-Boot头文件;尤其configs子目录下与目标板相关的配置头文件是移植过程中经常要修改的文件;
- lib_xxx 处理器体系相关的文件,如lib_ppc, lib_arm目录分别包含与PowerPC、ARM体系结构相关的文件;
- net 与网络功能相关的文件目录,如bootp,nfs,tftp;
- post 上电自检文件目录。尚有待于进一步完善;
- rtc RTC驱动程序;
- tools 用于创建U-Boot S-RECORD和BIN镜像文件的工具;
二、移植步骤
为了使U-Boot支持新的开发板,一种简便的做法是在U-Boot已经支持的开发板中选择一种和目标板接近的,并在其基础上进行修改。代码修改的步骤如下:
1)在board目录下创建smdk2410目录,添加smdk2410.c、flash.c、memsetup.s、u-boot.lds和config.mk等;
2)在cpu目录下创建arm920t目录,主要包含start.s、interrupts.c、cpu.c、serial.c和speed.c等文件;
3)在include/configs目录下添加smdk2410.h,它定义了全局的宏定义等;
4)修改u-boot根目录下的Makefile文件:
smdk2410_config : unconfig@./mkconfig
      $(@:_config=) arm arm920t smdk2410
5)运行make
      smdk2410_config,如果没有错误,就可以开始进行与硬件相关的代码移植工作。由于这部分代码与硬件紧密相关,所以要熟悉开发板的硬件配置,可参考各芯片的用户手册。
    当然,这个是一般步骤,后面我们做的可能具体文件名还和这个不一样,等到那时候在交待,这里先介绍的目的是在开始的时候给个大概的思路,要不直接分析源代码,有点在原始森林的感觉,耐心的看吧:)
三、start.S分析

先介绍start.S中的代码的具体作用,由于该代码是系统最开始执行的,这时,u-boot对系统一无所知,必须要初始化一些东西,比如设置异常的入口
地址和异常处理函数;配置PLLCON寄存器,确定系统的主频;屏蔽看门狗和中断;初始化I/O寄存器;关闭MMU功能;调用
/board/smdk2410中的memsetup.s,初始化存储器空间,设置刷新频率;将U-Boot的内容复制到SDRAM中;设置堆栈的大小,
然后ldr pc, _start_armboot,跳到C函数
代码来自华恒的板子上面的资料
/* CPU clcok */
/* 50.00 MHz */
#define MDIV_50                 0x5c
#define PDIV_50                 0x4
#define SDIV_50                 0x2
/* 100.00 MHz */
#define MDIV_100        0xa1
#define PDIV_100        0x3
#define SDIV_100        0x1
/* 200.00 MHz */
/*CPU clock = 202.800000 Mhz, HCLK = 101.400000 Mhz, PCLK = 50.700000 Mhz*/
/*0xa1  3  1*/
/*180Mhz 90Mhz 45Mhz  0x52  1  1*/
/*152MHZ              0x44 1   1*/
#define MDIV_200                0xa1
#define PDIV_200                0x3
#define SDIV_200                0x1
#define vMPLLCON_50             ((MDIV_50
系统分类: 软件开发
用户分类: LINUX
标签: 无标签
来源: 转贴
发表评论 阅读全文(417) | 回复(0)

1

2009年1月14日 - 心情挺好 - 心情挺好的博客
发表于 2008-9-5 18:17:24

s3c2410上移植uboot和linux2.6内核.虽然网上的文章多多,但真正要在自己的板子上跑起来还真是问题多。其间参考了不少网上同行们的文章,受益匪浅。最后我还将调制过程中遇到的问题总结列出,供后人参考。

点击看大图

问题一:Load Address  、Entry Point 设置问题
Starting kernel ...
undefined instruction
pc : [<c30008028>] lr : [<c0f91b14>]
sp : 33f4fc10 ip : 00000001 fp : 33f4fca4
r10: 33f9e70c r9 : 33ece9cd r8 : 33f4ffdcc
r7 : 33f4ffb8 r6 : 00000000 r5 : 00000000 r4 : 00000000
r3 : 30008000 r2 : c0000100 r1 : 000000c1 r0 : 00000000
Flags: nZCv IRQs off FIQs off Mode SVC_32
Resetting CPU ...

点击看大图

引导内核在这里进不去,网上也没一个很好的说法,由上图可知:Load Address 0x30008000 、Entry Point  0x30008000 ,#bootm的时候,显示是的内核前头加上的64byte的信息r1:000000c1 r0:00000000……按照上述制作uImage的方法设Load Address  、Entry Point 就ok。

/************下面引用了网上文章的原话********************************************************/

u-boot  调用 Linux 内核的方法是直接跳转到内核的第一条指令处,也即直接跳转到 MEM_START + 0x8000 地址处。在跳转时,要满足下列条件:

a) CPU 寄存器的设置: R0 = 0 ; R1 =机器类型 ID ,本系统的机器类型 ID = 193 。 R2 =启动参数标记列表在 RAM 中的起始基地址;

b) CPU 模式:必须禁止中断 (IRQs 和 FIQs) ; CPU 必须工作在 SVC 模式;

c) Cache 和 MMU 的设置: MMU 必须关闭;指令 Cache 可以打开也可以关闭;数据 Cache 必须关闭。

系统采用下列代码来进入内核函数:

theKernel = (void (*)(int, int))ntohl(hdr->ih_ep);

theKernel(0, bd->bi_arch_number); 其中, hdr 是 image_header_t 类型的结构体, hdr->ih_ep 指向内核的第一条指令地址,即 Linux 操作系统下的 /kernel/arch/arm/boot/compressed/head.S 汇编程序。 theKernel() 函数调用应该不会返回,如果该调用返回,则说明出错。

//theKernel(0, bd->bi_arch_number); 应该是:
      theKernel (0, bd->bi_arch_number, bd->bi_boot_params);

问题二:Starting kernel ...就没显示了.

点击看大图

郁闷吧,解决了第一个问题,又来了这个问题,什么都没显示了,错在哪呢?

theKernel (0, bd->bi_arch_number, bd->bi_boot_params);没有给内核正确传递参数?经过setenv修改启动参数、修改bi_arch_number的机器ID号,都未果,结果发现,优龙的linux-2.6.8.1-pxt1不能引导,我交叉编译Linux-2.6.25,制作uImage,结果正常启动,至于为什么linux-2.6.8.1-pxt1不能引导,我没做深入分析。

问题三:Uncompressing Linux....................................................... done, booting the kernel   就不动了

我没有遇到,摘用网上解法:一般这个错误有两种原因
一个内核的commandline ,一个是由于主频设置的问题
1. 通过go启动内核的话参数用的是编译时的..而bootm则是启动的经过处理的uImage(加了一个头)
所以用bootm就会把uboot设置的commandline传给内核..如果是用bootm启动出现bootint the 
kernel没显示了.则应该好好检查一下.可以printenv打印看uboot有没设置对commandline

2.主频问题,就是在MPLLCON这个寄存器的配置上。(board/s3c2410/s3c2410.c)
在VIVI:MPLLCON = 0x0005c040;计算出来的Mpll = 200Mhz
Uboot116:MPLLCON = 0x000a1031;计算出来的Mpll = 202Mhz
 那么,及有可能就是内核已经启动,而波特率不对,使打印出问题
把MPLLCON改成 = 0x0005c040就有显示了.

问题四:Error: unrecognized/unsupported machine ID (r1 = 0x33f4fca8)

点击看大图

分析:

tftp uImage到0x30008000,然后,go 0x30008000,这样uboot没有传参数给内核,go命令是不传递内核参数的所以会有Error: unrecognized/unsupported machine ID (r1 = 0x33f4fca8)这样的错误
一种方法是修改common/cmd_boot.c
/*#if defined(CONFIG_I386)*/          
  DECLARE_GLOBAL_DATA_PTR;        
/*#endif*/                                        
#if !defined(CONFIG_NIOS)
      /*******************add here*******************************/    
if(argc==2)
        rc = ((ulong (*)(int, char *[]))addr) (0, gd->bd->bi_arch_number);
  else      
/*********************add end *****************************/  
          rc = ((ulong (*)(int, char *[]))addr) (--argc, &argv[1]);
解决
还可以在arch/arm/kernel/head.S写死r1
mov    r1, #0xc1

个人建议不修改,用bootm命令。

至此,u-boot-1.1.6 移植完毕,感谢收看!

系统分类: 软件开发
用户分类: LINUX
标签: 无标签
来源: 转贴
发表评论 阅读全文(492) | 回复(0)

1

2009年1月14日 - 心情挺好 - 心情挺好的博客
发表于 2008-9-5 14:31:32

来自http://bbs.ednchina.com/ShowTopic.aspx?id=17046


    通常所说的JTAG大致分两类,一类用于测试芯片的电气特性,检测芯片是否有问题;一类用于Debug;一般支持JTAG的CPU内都包含了这两个模块。
一个含有JTAG Debug接口模块的CPU,只要时钟正常,就可以通过JTAG接口访问CPU的内部寄存器和挂在CPU总线上的设备,如FLASH,RAM,SOC(比如4510B,44Box,AT91M系列)内置模块的寄存器,象UART,Timers,GPIO等等的寄存器。

    上面说的只是JTAG接口所具备的能力,要使用这些功能,还需要软件的配合,具体实现的功能则由具体的软件决定。
    例如下载程序到RAM功能。了解SOC的都知道,要使用外接的RAM,需要参照SOC DataSheet的寄存器说明,设置RAM的基地址,总线宽度,访问速度等等。有的SOC则还需要Remap,才能正常工作。运行Firmware时,这些设置由Firmware的初始化程序完成。但如果使用JTAG接口,相关的寄存器可能还处在上电值,甚至时错误值,RAM不能正常工作,所以下载必然要失败。要正常使用,先要想办法设置RAM。在ADW中,可以在Console窗口通过Let 命令设置,在AXD中可以在Console窗口通过Set命令设置。
    下面是一个设置AT91M40800的命令序列,关闭中断,设置CS0-CS3, 并进行Remap,适用于AXD(ADS带的Debug)
setmem 0xfffff124,0xFFFFFFFF,32 ---关闭所有中断
setmem 0xffe00000,0x0100253d,32 ---设置CS0
setmem 0xffe00004,0x02002021,32 ---设置CS1
setmem 0xffe00008,0x0300253d,32 ---设置CS2
setmem 0xffe0000C,0x0400253d,32 ---设置CS3
setmem 0xffe00020,1,32 ---Remap
如果要在ADW(SDT带的DEBUG)中使用,则要改为:
let 0xfffff124=0xFFFFFFFF ---关闭所有中断
let 0xffe00000=0x0100253d ---设置CS0
let 0xffe00004=0x02002021 ---设置CS1
let 0xffe00008=0x0300253d ---设置CS2
let 0xffe0000C=0x0400253d ---设置CS3
let 0xffe00020=1 ---Remap
为了方便使用,可以将上述命令保存为一个文件config.ini, 在Console窗口输入 ob config.ini 即可执行。
    使用其他debug,大体类似,只是命令和命令的格式不同。


    设置RAM时,设置的寄存器以及寄存器的值必须和要运行程序的设置一致。一般编译生成的目标文件是ELF格式,或类似的格式,包含有目标码运行地址,运行地址在Link时候确定。Debug下载程序时根据ELF文件中的地址信息下载程序到指定的地址。如果在把RAM的基地址设置为0x10000000, 而在编译的时候指定Firmware的开始地址在0x02000000, 下载的时候,目标码将被下载到0x02000000,显然下载会失败。

    通过JTAG下载程序前应关闭所有中断,这一点和Firmware初始化时关闭中断的原因相同。在使用JTAG接口的时候,各中断的使能未知,尤其是FLASH里有可执行码的情况,可能会有一些中断被使能。使用JTAG下载完代码,要执行时,有可能因为未完成初始化就产生了中断,导致程序异常。所以,需要先关闭中断,一般通过设置SOC的中断控制寄存器完成。

    使用JTAG写Flash。在理论上,通过JTAG可以访问CPU总线上的所有设备,所以应该可以写FLASH,但是FLASH写入方式和RAM大不相同,需要特殊的命令,而且不同的FLASH擦除,编程命令不同,而且块的大小,数量也不同,很难提供这一项功能。所以一般Debug不提供写Flash功能,或者仅支持少量几种Flash。

    目前就我知道的,针对ARM,只有FlashPGM这个软件提供写FLASH功能,但使用也非常麻烦。AXD,ADW都不提供写FLASH功能。我写Flash的方法时是,自己写一个简单的程序,专门用于写目标板的FLASH,利用JTAG接口,下载到目标板,再把要烧写的目标码装成BIN格式,也下到目标板(地址和烧FLASH的程序的地址不同),然后运行已经下载的烧FLASH的程序。使用这种方式,比起FlashPGM的写Flash,速度似乎要快一些。
 
    关于简单JTAG电缆。
    目前有各种各样简单JTAG电缆,其实只是一个电平转换电路,同时还起到保护作用。JTAG的逻辑则由运行在PC上的软件实现,所以在理论上,任何一个简单JTAG电缆,都可以支持各种应用软件,如Debug等。我就曾使用同一个JTAG电缆写Xilinx CPLD,AXD/ADW调试程序。关键再于软件的支持,大多数软件都不提供设定功能,因而只能支持某种JTAG电缆。

    关于简单JTAG电缆的速度。
    JTAG是串行接口,使用打印口的简单JTAG电缆,利用的是打印口的输出带锁存的特点,使用软件通过I/O产生JTAG时序。由JTAG标准决定,通过JTAG写/读一个字节要一系列的操作,根据我的分析,使用简单JTAG电缆,利用打印口,通过JTAG输出一个字节到目标板,平均需要43个打印口I/O, 在我机器上(P4 1.7G),每秒大约可进行660K次 I/O 操作,所以下载速度大约在660K/43, 约等于15K Byte/S. 对于其他机器,I/O速度大致相同,一般在600K ~ 800K.

    关于如何提高JTAG下载速度。
很明显,使用简单JTAG电缆无法提高速度。要提高速度,大致有两种办法,
1。使用嵌入式系统提供JTAG接口,嵌入式系统和微机之间通过USB/Ethernet相连,这要求使用MCU。
2。使用CPLD/FPGA提供JTAG接口,CPLD/FPGA和微机之间使用EPP接口(一般微机打印口都支持EPP模式),EPP接口完成微机和CPLD/FPGA之间的数据传输,CPLD/FPGA完成JTAG时序。

    这两种方法本人都实现过。第一个方法可以达到比较高的速度,实测超过了200KByte/S(注意:是Byte,不是Bit);但是相对来说,硬件复杂,制造相对复杂。第二种相对来说,下载速度要慢一些,最快时达到96KByte/S,但电路简单,制造方便,而且速度可以满足需要。第二种方案还有一个缺点,由于进行I/O操作时,CPU不会被释放,因此在下载程序时,微机CPU显得很繁忙。
总的来说,本人认为,对于个人爱好者来说,第二种方法更可取。

系统分类: 软件开发
用户分类: LINUX
标签: 无标签
来源: 转贴
发表评论 阅读全文(216) | 回复(0)

2

2009年1月14日 - 心情挺好 - 心情挺好的博客
发表于 2008-9-4 22:30:20



ARM汇编语言源程序语句,一般由指令,伪操作,宏指令和伪指令作成.

ARM汇编语言的设计基础是汇编伪指令,汇编伪操作和宏指令.

    伪操作,是ARM汇编语言程序里的一些特殊的指令助记符,其作用主要是为完成汇编程序做各种准备工作,在源程序运行汇编程序处理,而不是在计算机运行期间有机器执行.也就是说,这些伪操作只是汇编过程中起作用,一旦汇编结束,伪操作的使命也就随之消失.

    宏指令,是一段独立的程序代码,可以插在程序中,它通过伪操作来定义,宏在被使用之前必须提前定义好,宏之间可以互相调用,也可自己递归调用.通过直接书写宏名来使用宏.并本具宏指令的格式输入输出参数.宏定义本身不产生代码,只是在调用它时把宏体插入到原程序中.宏与C语言中的子函数形参和实参的调用相似,调用宏时通过实际的指令来  代替宏体实现相关的一段代码,但宏的调用与子程序的调用有本质的区别,既宏并不会节省程序的空间,其优点是简化程序代码,提高程序的可读性以及宏内容可以同步修改.

    伪操作,宏指令一般与编译程序有关,因此ARM汇编语言的伪操作,宏指令在不同的编译环境下有不同的编写形式和规则.
   
    伪指令也是ARM汇编语言程序里的特殊助记符,也不在处理器运行期间由机器执行,他们在汇编时将被合适的机器指令代替成ARM或Thumb指令,从而实现真正的指令操作.
   
    目前常用的ARM编译环境有2种.
 

      1.       ADS/SDT IDE:ARM公司开发,使用了CodeWarrior公司的编译器.

      2.       集成了GNU开发工具的IDE开发环境;它由GNU的汇编器as,交叉汇编器gcc和连接器id组成.

 ADS编译环境下的ARM伪操作和宏指令,可参考北航出版社的<<ARM微控制器基础与实践》(周立功)

 这里主要讲述ARM GNU常用汇编语言
 
4 ARM GNU常用汇编语言介绍

4.1 ARM GNU常用汇编伪指令介绍
1. abort
.abort: 停止汇编

.align absexpr1,absexpr2:
以某种对齐方式,在未使用的存储区域填充值. 第一个值表示对齐方式,4, 8,16或32. 第二个表达式值表示填充的值.

2. if...else...endif
.if
.else
.endif: 支持条件预编译

3. include
.include "file": 包含指定的头文件, 可以把一个汇编常量定义放在头文件中.
4. comm
.comm  symbol, length:在bss段申请一段命名空间,该段空间的名称叫symbol, 长度为length. Ld连接器在连接会
为它留出空间.

5. data
.data subsection: 说明接下来的定义归属于subsection数据段.

6. equ
.equ symbol, expression: 把某一个符号(symbol)定义成某一个值(expression).该指令并不分配空间.

7. global
.global symbol: 定义一个全局符号, 通常是为ld使用.

8. ascii
.ascii "string": 定义一个字符串并为之分配空间.

9. byte
.byte expressions: 定义一个字节, 并为之分配空间.

10. short
.short expressions: 定义一个短整型, 并为之分配空间.

11. int
.int expressions: 定义一个整型,并为之分配空间.

12 long
.long expressions: 定义一个长整型, 并为之分配空间.

13 word
.word expressions: 定义一个字,并为之分配空间, 4bytes.

14. macro/endm
.macro: 定义一段宏代码, .macro表示代码的开始, .endm表示代码的结束.

15. req
name .req register name: 为寄存器定义一个别名.

16. code
.code [16|32]: 指定指令代码产生的长度, 16表示Thumb指令, 32表示ARM指令.

17. ltorg
.ltorg: 表示当前往下的定义在归于当前段,并为之分配空间.

4.2 ARM GNU专有符号
1. @
表示注释从当前位置到行尾的字符.

2. #
注释掉一整行.

3. ;
新行分隔符.

4.3 操作码

1. NOP
nop
空操作, 相当于MOV r0, r0

2. LDR
ldr <register> , = <expression>
相当于PC寄存器或其它寄存器的长转移.

3.ADR
adr <register> <label>
相于PC寄存器或其它寄存器的小范围转移.

ADRL
adrl <register> <label>
相于PC寄存器或其寄存器的中范围转移.


5 可执行生成说明

5.1 lds文件说明

5.1.1 主要符号说明

    1. OUTPUT_FORMAT(bfdname)
    指定输出可执行文件格式.
   
    2. OUTPUT_ARCH(bfdname)
   
    指定输出可执行文件所运行CPU平台
   
    3. ENTRY(symbol)
    指定可执行文件的入口段
   
    5.1.2 段定义说明
    1. 段定义格式
    SECTIONS
    { ...
        段名 :
        {
            内容
        }
    ...
    }

系统分类: 软件开发
用户分类: LINUX
标签: 无标签
来源: 转贴
发表评论 阅读全文(178) | 回复(0)

2

2009年1月14日 - 心情挺好 - 心情挺好的博客
发表于 2008-9-4 22:28:11
 
前言:

以前用ARM的IDE工具,使用的是ARM标准的汇编语言。现在要使用GNU的工具,当然要了解一点GNU ARM汇编的不同之处。其实非常的简单,浏览一下文档然后再看看程序就完全可以搞定了,或者你硬着头皮看GNU ARM的汇编程序,用不了多少时间你就就可以无师自通了。个人比较健忘,还是把文档翻译了一下,算是给自己一个避免遗忘的理由吧。

ARM汇编语言源程序语句,一般由指令,伪操作,宏指令和伪指令作成.ARM汇编语言的设计基础是汇编伪指令,汇编伪操作和宏指令.

目前常用的ARM编译环境有2种:
ARMASM: ARM公司的IDE中使用了CodeWarrior的编译器,绝大多数windows下的开发者都在使用这一环境,完全按照ARM的规定;
GNU ARM ASM: GNU工具的ARM版本,与ARMASM略有不同;

关于CodeWarriror ARM汇编的书和文章很多,本文假定你已经完全了解ARMASM,这里只说明GNU ARM汇编,并针对ARMASM给出说明。本文翻译自:GNU ARM Assembler Quick Reference, 本人水平有限,错误难免,转载随意,请注明出处。英文原文地址不详。


GNU ARM 汇编快速入门

任何汇编行都是如下结构:
 
[<label>:] [<instruction or directive>} @ comment
[<标签>:] [<指令>} @ 注释
 
GNU ARM 汇编中,任何以冒号结尾的都被认为是一个标签,而不一定非要在一行的开始。下面是一个简单的例子,这段汇编程序定义了一个"add"的函数,该函数返回两个参数的和:
 
.section .text, “x”
.global add @ give the symbol add external linkage
add:
ADD r0, r0, r1 @ add input arguments
MOV pc, lr @ return from subroutine
@ end of program
 
GNU ARM汇编伪指令

下面列出了一些GNU ARM汇编伪指令,并给出了相应说明。

.ascii “<string>” 在汇编中定义字符串并为之分配存储空间(与armasm中的DCB功能类似)。
.asciz “<string>” 和.ascii类似, 但不分配存储空间。
 
.balign <power_of_2> {,<fill_value> {,<max_padding>} }
以某种排列方式在内存中填充数值。 (该指令与armasm中的ALIGN类似)。
power_of_2表示排列方式,其值可为4,8,16或32,单位是byte;
fill_value是要填充的值;
max_padding最大的填充界限,请求填充的bytes数超过该值,将被忽略。
 
.byte <byte1> {,<byte2>} … 定义一个或多个Byte,并为之分配空间(与armasm的DCB类似)。 
.code <number_of_bits> 设定指令宽度,16表示Thumb,32表示ARM assembly
(和armasm中的CODE16,CODE32相同)。
 
.if 
.else
.endif
预编译宏(与armasm中的IF ELSE ENDIF相同)。
 
.end 汇编文件结束标志,常常省略不用。

.endm 宏结束标志。
.exitm 宏跳出。
.macro <name> {<arg_1} {,<arg_2>} … {,<arg_N>}
定义一段名为name的宏,arg_xxx为参数。
必须有对应的.endm结尾。
可以使用.exitm从中间跳出宏。(与armasm中的MACRO, MEND, MEXIT相同)。
在使用宏参数时必须这样使用:“\<arg>”。
例如:
[CODE].macro SHIFTLEFT a, b
.if \b < 0
MOV \a, \a, ASR #-\b
.exitm
.endif
MOV \a, \a, LSL #\b
.endm

.rept <number_of_times> 循环执行.endr前的代码段number_of_times次。
(与armasm中的WEN相似)

.irp <param> {,<val_1>} {,<val_2>} …
循环执行.endr前的代码段,param依次取后面给出的值。
在循环执行的代码段中必须以“\<param> ”表示参数。

.endr 结束循环(与armasm中的WEND相似).
 
.equ <symbol name>, <value> 为一个标号赋值,类似C中的#define。(与armasm中的EQU相同)
 
.err 编译错误报告,将引起编译的终止。
 
.global <symbol> 全局声明标志,这样声明的标号将可以被外部使用。(与armasm中的EXPORT相同)。
 
.hword <short1> {,<short2>} …
插入一个16-bit的数据队列。(与armasm中的DCW相同)
 
.ifdef <symbol> 如果 <symbol>被定义,该快代码将被编译。以 .endif结束。
.ifndef <symbol> 如果 <symbol>未被定义,该快代码将被编译。以 .endif结束。
 
.include “<filename>” 包含文件。(与armasm中的INCLUDE 或者C中的#i nclude一样)
 
<register_name> .req <register_name>
定义一个寄存器,.req的左边是定义的寄存器名,右边是使用的真正使用的寄存器。
(与armasm中的RN类似)
例如:acc .req r0
 
[CODE].section <section_name> {,”<flags>”}
开始一个新的代码或数据段。.text, 代码段;.data, 初始化数据段;.bss, 未初始化数据段。
这些段都有缺省的标志(flags),联接器可以识别这些标志。(与armasm中的AREA相同)。
下面是ELF格式允许的段标志
<标志> 含义
a 允许段
w 可写段
x 执行段
 
.set <variable_name>, <variable_value> 变量赋值。(与armasm中的SETA相同)
 
.space <number_of_bytes> {,<fill_byte>}
分配number_of_bytes字节的数据空间,并填充其值为fill_byte,若未指定该值,缺省填充0。
(与armasm中的SPACE功能相同)
 
.word <word1> {,<word2>} …
插入一个32-bit的数据队列。(与armasm中的DCD功能相同)

GNU ARM汇编特殊字符和语法
 
代码行中的注释符号: ‘@’
整行注释符号: ‘#’
语句分离符号: ‘;’
直接操作数前缀: ‘#’ 或 ‘$’
 
.arm 以arm格式编译,同code32
.thumb 以thumb格式编译,同code16
.code16 以thumb格式编译
.code32 以arm格式编译
 
篇后语:

更详细的使用说明请参照:ARM Architecture Reference Manual, Addison-Wesley ISBN 0-201-73719-1

译者:

重要的部分翻译完成了,本人认为不重要的没有翻译,如force_thumb,寄存器命名等等。
系统分类: 软件开发
用户分类: LINUX
标签: 无标签
来源: 转贴
发表评论 阅读全文(136) | 回复(0)

2

2009年1月14日 - 心情挺好 - 心情挺好的博客
发表于 2008-9-4 19:12:14
摘  要:针对Linux移植S3C2410微处理器系统开发的需要,设计了S3C2410外围存储系统。本文研究了S3C2410的寻址原理,并结合该芯片SDRAM时序图详细分析了其对SDRAM寻址的全过程。介绍了与存储系统设计相关的控制寄存器和引脚,给出了与Flash和SDRAM的硬件电路连接图。最后在启动代码U-Boot下实现了存储系统的初始化。嵌入式开发人员可以根据开发需要借鉴本文的设计思路扩展其它ARM核芯片的存储系统。
关键词:S3C2410;寻址原理;SDRAM寻址机制;U-Boot

0 引言

Samsung公司推出的基于ARM920T内核的16/32位RISC微处理器S3C2410,为手持设备和一般类型应用提供了低价格、低功耗、高性能小型微控制器的解决方案。为了降低整个系统的成本,S3C2410提供了丰富的内部设备。其中加强的ARM体系结构MMU用于支持WinCE,EPOC32和Linux。随着技术的进步和发展,电子产品的功能日益强大,而嵌入式操作系统可以有效地管理各项功能,并且能够缩短产品开发周期,因此将微处理器与嵌入式操作系统进行联合开发成为一种趋势,然而微处理器的片内存储资源有限,若要进行嵌入式系统的移植,必须扩展其存储系统。对于嵌入式系统的开发人员来说,深入理解其存储系统原理和有效地管理存储系统对正确高效地设计嵌入式系统的硬件和底层软件编程具有重要的意义[1]

1 S3C2410的寻址原理

ARM920T内核提供了32位的地址总线,可以访问4G(232)的线性地址空间,而S3C2410的内部地址总线是30bit(HADDR[29:0]),能够访问的最大外部地址空间是230,即1G的地址空间0x00000000~0x3FFFFFFFF,可见S3C2410仅利用了ARM920T的32位地址总线的低30位,并且是一一对应相连的[1]。由表1可知S3C2410将1G的外部地址空间分成了8个存储器组,每个组的大小为128M,其中6个用于ROM、SRAM等存储器,2个用于ROM、SRAM、SDRAM等存储器。基于芯片体积及成本的考虑,当S3C2410对外寻址时,采用了部分译码的方式,即低位地址线用于外围存储器的片内寻址,而高位地址线用于外围存储器的片外寻址。如表1所示,由于每个存储器组的起始地址及空间大小固定,对于系统要访问的任意外部地址,S3C2410可以方便地利用内部地址总线的高3位HADDR[29:27]来选择该地址属于哪一个存储器组(Bank),从而激活相应的Bank选择信号,并且使用外部地址总线A[26:0]来实现相应Bank的内部寻址,寻址范围为128M(227),从而使得其外围地址访问空间为1GB(128MB×8)。S3C2410正是通过这种机制来完成外部地址空间的寻址全过程。

表 1 S3C2410存储器组片选激活及地址空间分配

HADDR29

HADDR28

HADDR27

片选信号

片选控制

寄存器

地址空间

0

0

0

nGCS0

BANKCON0

0x00000000~0x07FFFFFF

0

0

1

nGCS1

BANKCON1

0x08000000~0x0FFFFFFF

0

1

0

nGCS2

BANKCON2

0x10000000~0x17FFFFFF

0

1

1

nGCS3

BANKCON3

0x18000000~0x1FFFFFFF

1

0

0

nGCS4

BANKCON4

0x20000000~0x27FFFFFF

1

0

1

nGCS5

BANKCON5

0x28000000~0x2FFFFFFF

1

1

0

nGCS6

BANKCON6

0x30000000~0x37FFFFFF

1

1

1

nGCS7

BANKCON7

0x38000000~0x3FFFFFFF

 

S3C2410访问SDRAM地址空间的过程比较难理解,这主要和SDRAM的存储结构有关。为了更深入地理解其寻址机制,笔者以SDRAM芯片HY57V561620B(32MB)为例进行详细地说明。该芯片的内部存储结构是4Banks×4M×16Bit,即共有4个Bank,每个Bank中有4M个半字(16Bit)。Bank地址可以通过BA[1:0]与地址总线的高位相连来确定,具体BA[1:0]与哪个地址位相连,不同的SDRAM存储系统有不同的方案,详见参考文献[3]。而每个Bank中的存储单元由行地址和列地址来唯一标识[1],该芯片通过行地址锁存引脚nRAS和列地址锁存引脚nCAS分别与S3C2410的引脚nSRAS(SDRAM行地址选通信号)和nSCAS(SDRAM列地址选通信号)连接,从地址总线获得行地址和列地址。而且列地址的位数可以在BANKCONn(n=6,7)的中的SCAN——BANKCONn [1:0]来配置,00=8-bit,01=9-bit,10=10-bit,其复位值为00,即8bit。

在实际工作中,如图1所示,在第3个总线时钟,nSCS为低电平,表示SDRAM被选中,并且地址线的Bank地址与相应的行地址同时发出,这个命令称之为“行有效”或“行激活”(Row Active)。此时SDRAM将行地址锁存(nSRAS有效),但还没有执行写命令(nWE为高电平),因为没有列地址(nSCAS为高电平),存储单元无法确定。经过Trcd(RAS至CAS延迟)后,SDRAM再次被选中(nSCS为低电平),此时nSCAS为低电平,指示SDRAM此时地址线上的地址为列地址,同时nWE有效,写操作被执行。可见发送列地址寻址命令与具体的操作命令(是读还是写),这两个命令也是同时发出的,所以一般都会以“读/写命令”来表示列寻址,相关的列地址被选中之后,将会触发数据传输。至此,S3C2410对SDRAM的寻址就完成了。可见,S3C2410将地址总线上的地址分成行地址和列地址并分开传输给SDRAM。基于上述的寻址机制,由BA[1:0]和12根地址线就可以寻址32M或更大的地址空间了。

2009年1月14日 - 心情挺好 - 心情挺好的博客

图 1 S3C2410 SDRAM时序图

2 存储器控制器和相关引脚介绍

2.1寄存器介绍

S3C2410存储器控制器主要有:总线带宽和等待控制寄存器(BWSCON);总线控制寄存器(BANKCONN:nGCS0-nGCS5);BANK控制寄存器(BANKCONn:nGCS6-nGCS7);刷新控制寄存器(REFRESH);BANKSIZE寄存器;SDRAM模式寄存器集寄存器(MRSR)等,详情请见参考文献[3]。

2.2相关引脚

S3C2410提供了相关的引脚来控制存储器访问:

组选择信号:nGCS0-nGCS5,nGCS6(nSCS0),nGCS7(nSCS1)引脚用来选择相应的存储器组。

访问控制信号:为了实现ARM存储器访问指令LDR/STR字节、半字和字访问的三种方式,在S3C2410的存储器组中,除了Bank0以外的所有地址空间都可以通过编程设置为8位、16位或32位对准访问,Bank0可以设置为16位或32位。引脚nWBE[3:0](写字节使能)实现8bit ROM芯片组的三种访问方式,或者SRAM不使用UB/LB(在BWSCON中设置)的情况下,与UB/LB连接。引脚nBE[3:0](在使用SRAM情况下的字节允许信号)在SRAM使用UB/LB(是否使用可在BWSCON中设置)的情况下与UB/LB连接。DQM[3:0](SDRAM数据屏蔽信号)引脚实现对SDRAM的三种访问。还有nWAIT、nXBREQ/nXBACK引脚。

3 硬件电路设计

在本嵌入式系统开发实验中,S3C2410扩展的存储系统采用了英国Intel公司的16M E28F128J3A-150 NOR Flash芯片,以及Hynix公司的32M HY57V561620B SDRAM芯片。地址空间分配如下:Flash为Bank0中的0x00000000~0x07FFFFFF地址段,而SDRAM为Bank6中的0x30000000~0x37FFFFFF地址段,具体的电路连接如图2。

2009年1月14日 - 心情挺好 - 心情挺好的博客

图 2 S3C2410 与Flash、SDRAM的电路连接图

4 存储系统初始化

U-Boot是德国DENX小组的开发用于多种嵌入式CPU的开放源代码bootloader程序,目前最新版本是1.1.6,本实验使用的是U-Boot-1.1.4。U-Boot是在ppcboot以及armboot的基础上发展而来,现已非常成熟和稳定,已经在许多嵌入式系统开发过程中被采用。其支持多种目标操作系统,其中对Linux的支持最完善,是嵌入式Linux Bootloader的最佳选择。

由于本实验Linux要移植的开发板是基于s3c2410的开发板,在U-Boot中已有移植成功的smdk2410开发板,故以smdk2410开发板上运行的U-Boot为模板设计适合本实验的U-Boot。有关存储系统的初始化修改如下:

(1)Flash驱动程序采用了board/Cmi/Flash.c,由于cmi中的flash.c在写入时要交换字节,因而删除了它的write_short()和write_buff()函数,利用board/ep7312/Flash.c中的write_word()和write_buff()函数,并且把flash.c中的FLASH_BASE0_PRELIM改为CFG_FLASH_BASE。把FLASH_BLOCK_SIZE改为0x20000,(E28F128J3A flash中块的大小是128K)。

(2)Board/ smdk2410/smdk2410.c中函数dram_init()定义了SDRAM的真实地址和实际大小。由于本实验中,SDRAM的大小为32M,所以修改Include/configs/Smdk2410.h中的PHYS_SDRAM_1_SIZE,改为0x02000000。

(3)将如下代码替代原来在Include/configs/Smdk2410.h的/*FLASH and environment organization*/一栏中的内容。

#define PHYS_FLASH_1 0x00000000                /* Flash Bank #1 */
#define PHYS_FLASH_SIZE 0x01000000           /* 16 MB */
#define CFG_FLASH_PROTECTION
#define CFG_FLASH_BASE PHYS_FLASH_1
#define CFG_MONITOR_BASE PHYS_FLASH_1
#define CFG_MAX_FLASH_BANKS 1        /* max number of memory banks */
#define CFG_MAX_FLASH_SECT 128              /* max number of sectors on one chip */
#define CFG_FLASH_ERASE_TOUT (2*CFG_HZ)    /* Timeout for Flash Erase */
#define CFG_FLASH_WRITE_TOUT (2*CFG_HZ)   /* Timeout for Flash Write */
#define CFG_ENV_IS_IN_FLASH 1
#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x60000)
#define CFG_ENV_SIZE 0x20000                     /* Total Size of Environment Sector */

如上分析,SDRAM和Flash的初始化信息分别在smdk2410.c和flash.c文件中定义了,最后是通过lib_arm/board.c文件的display_dram_config()和display_flash_config()函数来显示的。

5 结束语

本文结合实际实验,分析了S3C2410的存储系统原理,完成了其外围存储系统的硬件电路设计和软件初始化,最后成功实现了对S3C2410存储系统的存取访问。开发人员可以根据笔者的研究和设计思路,同时结合所需的存储容量和类型进行高效的存储系统设计。

本文作者的创新点:从S3C2410芯片寻址原理的研究和存储芯片时序图的分析,实现了其外围存储系统的硬件设计和软件编程,展现了S3C2410与外围存储系统的相互访问机制,力求设计思路更加清晰,有利于嵌入式系统的调试,从而提高其稳定性。

参考文献:

[1]      袁夫全等.基于S3C4510B的存储系统原理与设计.微计算机信息.2005,21(2):99-101

[2]      ARM9TDMI datasheet.pdf

[3]      S3C2410X datasheet.pdf

[4]      田泽.ARM9嵌入式开发实验与实践.北京:北京航天航空大学出版社.2006.10

  评论这张
 
阅读(1277)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018