Jflash-s3c2410(linux 版本)源码分析
最近在远峰公司买了arm9的板子,S3C2410,ARM920T ,没有Nor flash ,Nand Flash 是64M ,SDRAM 是K9f1208,本人对linux 的热情大于windows ,所以想在linux 下做开发,可是远峰公司只给我 文件,而且没有源代码,每次在linux 下编译好了后还得切换到windows 下烧录,很是麻烦,于是在网上了很多Jflash 类似的程序,不过不同的烧录针对不同的硬件平台,Jflash 是跟硬件紧密结合的,比如有的针对Nor Flash ,有的针对Nand Flash 的,不同内核有不同的Jflash ,而且相同的内核也有不同的版本,因为Jtag 的原理图不同,就只能有相对应的Jflash ,程序中的定义要与pc 机并口与Jtag 接口的对应相一致。
在进入源码分析之前要介绍一些预备的知识,有助于理解源代码,毕竟这个程序和硬件联系很紧密的。首先介绍一下对PC 并口做一些简要的介绍
一、PC 标准配备并行口介绍
本文主要介绍计算机的标准配备并行端口即25针的母接头端口的应用,在此基础上可以运用相同的原理使用其它模式的并行端口。并行端口共有25支脚,但不是每支脚均被使用到。这些脚被区图1
分为3种主要的功能,分别是用于数据的传送、检查打印机的状态及控制打印机,其接口如下所示:
注:18~脚为GND
在PC 机中,标准并行口使用3个8位对这些寄存器,
也就是所说的数据、
25号的端口寄存器,PC 就是通过状态、控制寄存器的读写访问并口的信号的。本文中使用一些通用的叫法,8个数据位分别为D0~D7,5个状态位为S3~S7,4个控制为C0~C3。其中字母表示了端口寄存器,数字则表示该信号在
寄存器中的位。
数据寄存器
据端口或称数据寄存器(D0~D7)保存了写入数据输出端口的一字节信息。数据端口可以写入数数据寄存器(即数据输出端口)可擦写、基地址
数据,也可以读出数据(即可擦写);写进去的当然是我们希望从数据端口引脚输出的数据,不过读进来的也只是我们上次写进去的数据,或是原来保留在里面的数据,并不是从端口引脚输入PC 的数据。数据端口引脚是PIN2~PIN9,其定义如下:
bit 引在连接器处倒相
脚 信号 信号源 是否0 Pin2 D  ATA0PC 否
1 Pin3 DATA1 PC 否
2 Pin4 DATA2 PC 否
3 Pin5 DATA3 PC 否
4 Pin6 DATA4 PC 否
5 Pin7 DATA5 PC 否
6 Pin8 DATA6 PC 否
7 Pin9 DATA7 PC
否 图2
如果我们把这8支脚当成一般的数字输出的脚位看待,上述8支脚就相当于是8个数字输出的位置一态寄存器
状态端口或称状态寄存器保存的是5个输入(S3~S7)的逻辑状态。S0~S2位不出现在并口连接器中入端口)基地址+1
般,我们就可以把它们当成是8个可以自由控制的输出点。当我们通过数据端口传送数据时,就是改变这8支脚的电平状态;而接受方也按照相同的编码原则解释,就可以获得传送的数据。
。除了S0以外,状态寄存器是只读的,读出数据信息是状态端口引脚上的逻辑状态。S0是支持EPP 传
输并口的超时标志信息,可以用软件方法清零。在许多并口中,状态输入接有上拉电阻。状态端口引脚是Pin10~Pin13、Pin15,其定义如下:
状态寄存器(即状态输bit 引脚是否在连接器处倒相 信号名 信号源
0  T  ime-Out  1  未使用
2  未使用
3 Pin 5 nError(nFault) 外设 否
14 Pin13 Select 外设 否
5 Pin12 P  aperEnd 外设 否
6 Pin10 nAck 外设 否
7 Pin11 Busy 外设
是 图3
上表中所谓的(基地址+1)指的是:如果我们PT 地址是378H ,在加上1就是379H ;这个地址的L 是专门用来传递打印机的状态的。和数据地址比较起来不一样的是,这里地址并非在连接器的脚位上均有对应点。在这个状态的显示上只有5个脚位有对应,位S0~S2是没有的--最起码是无法
让计算机有对应的值可读取。 如果打印机接到并口上,那么打印机的状态将会通过这几支脚传送到PC ,程序只要去基地址
+1的位置读取数值即可知道现在打印机所处的状态。由于这几支脚可以让打印机传送状态给PC ,制寄存器
制端口或称控制寄存器保存了C0~C3的4位的控制信息。C4~C7不出现在并口连接器中。一般地址+2
那么我们可以把这几支脚位拿来当作数字输入的通道;我们可以让这几支脚位的状态发生电位的改变,而利用程序去读取这些脚位的数值,即可实现数据的输入。
控来说,这些位被用来输出,然而大多数SPP 中,控制位为集电极开路/漏极开路模式,也就是说,它们同样可以用作输入。要从控制位上读取外部逻辑信号,首先将向相应的输出写入“1”,然后读取控制寄存器的值即可。但是,为了提高交换速度,大多数支持EPP 和ECP 接口中,控制位工作在不能用作输
入的推拉模式下。在一些多模式接口中,控制位采用的是改进型的推拉模式,可以用作输入。控制端口引脚是Pin1、Pin14、Pin16和Pin17,其定义如下:
控制寄存器(即控制输出端口)基bit 是否在连接器处倒相
引脚 信号名 信号源 0 Pin1 nStrobe PC 是
1 Pin14 nAutoLF PC 是
2 Pin16 nInit PC 否
3 Pin17 nS n electI PC 是
4  IRQ
5  未使用
6  未使用
7  未使用
图4
上表中所谓的(基地址+2)指的是:如果我们的LPT 地址是378H ,在加上1就是37AH ;这个地址寄存器和状态寄存器。根据图1可知用到了、Jflash 源代码分析
具体的配置,我们针对的是s3c2410, Nand Flash 64M 、无Nor Flash ,s3c2410,的文件:
是专门用来控制打印机动作的。 如同数据的送出,我们的程序只要将我们的信息送往(基地址+2)的地址去,就可以实现数据输出,接受端在相应引脚就可以接受到相应的逻辑电位状态。当控制端口的信号源为高电平时,这些引脚可以作为输入引脚,如同状态端口引脚一样。 在上述定义表格中,所谓“是否在连接器处倒相”是指并口硬件将连接器与相应寄存器位之间的4个信号进行了倒相处理。具体说来,S7、C0、C1、C3信号的逻辑状态在连接器处是与相应寄存器位反相的。当你对这些位进行写操作时,必须牢记写入的值应该与你想在连接器处设置的值相反;当要对这些位进行读操作时,也必须记住所读取的值与连接器处的值相反。 计算机的标准配备并行端口除以上介绍的数据端口引脚Pin2~Pin9、状态端口引脚Pin15、Pin10~Pin13、控制端口引脚Pin1、Pin14、pin16、Pin17外,连接器上的 其它引脚Pin18~Pin25是归地引脚GND 。
在与Jtag 相连接是控制寄存器是没有用到,只用到了数据Pin2、Pin3、Pin8、Pin11分别对应数据寄存器的DATA0、DATA1、DATA6和状态寄存器的位7即信号名Busy 。
二源代码分析总是要针对默认是从Nand Flash 启动.下面的分析都是基于上面的配置,不同的配置可以
做相应的修改,以满足不同的硬件环境。
在Jflash 中有如下
Def.h  Jtag.c Jtag.h K9sxx08.c K9sxx08.h  Pin2410.c Pin2410.h  Ppt.c Ppt.h  Sjf.c  Sjf.h c 中,那2410的一般的使用方法是:
otloader.bin  /t=5
在Sjf.c 中有这样的函数void 取得目标文件的大小这里是函数中调用了另一个函数int GetValidPpt(void),该函数unsigned long port )
if (ioperm (port, 3, 1)) {
ioperm (0x80, 1, 1)) {
urn 1;
函数目的取得在Ppt.h 中定义的端口的控制权
hen 2 then 3
er if needed for multiple ports)
po 数是取得或关闭对端口的控制权,port sm/unistd.h 中定义的,它是个系统调用。
护模式下,不能直接对端口进行存取,需先通过系统调用ioperm 取得对端口的控erm (port, 3, 1)目的是取得对三个端口的控制权,是并口的数据寄存器端口,状态寄存器端口,控制寄调用了个(ioperm (0x80, 1, 1),它的目的是取得对0x80端口的控制权,因为在函数int G 如果一致,说明该端口是可用的,否我用的是Nand Flash K9f1208和K9s1208参数基本是一样的,两者可以通用。主函数在Sjf.我们先从这里开始。
在linux 下用Jflash-s3c ./Jflash-s3c2410  bo  OpenImageFile(char *filename); 它用来bootloader.bin 文件的大小,放在全局变量U32 imageSize;中、在函数void ErrorBanner(void)中只是介绍一些Jflash 的使用说明,没有必要关注。
当执行到函数void OpenPpt(void)时,在该中Ppt.c 文件中定义的,在int GetValidPpt(void)函数中调用了int io_access_on( unsigned long port )函数,这个函数如下:
int io_access_on( {
perror ("ioperm()");
return 0;
}
if (        perror ("ioperm()");
return 0;
}
ret }
该#define LPT1 0x378 // the search order is LPT1 t #define LPT2 0x278 // first valid address found is used (re-ord #define LPT3 0x3bc // hardware base address for parallel port
ioperm(unsigned long rt , unsigned long num,bool on_off)这个函是指的端口的基地址,num 是连续的端口数目,on_off 表明是获得控制权(on_off=1),还是释放控制权(on_off=0)。
该函数是在include/a #define __NR_ioperm 101
因为linux 程序运行在保制权。Linux 的ioperm 系统调用允许本地读/写访问系统的I/O 端口,ioperm 由
于设计问题可允许非特权用户获得对系统I/O 端口的读和写访问。当特权进程使用时,ioperm 系统调用也会不正确地限制权限。
iop 存器端口。
在该函数中还etValidPpt(void)中调用了_outp(),_inp(),它们其实是宏指令,在对端口进行存取后需要延迟1~2毫秒才能完成,而这些宏指令中会利用对端口0x80输出数据来达到延迟时间的目的,在对端口0x80输出数据时,并不影响系统,故先要取得对端口0x80得到控制权。
取得控制权后,向端口写入个数据0x55,在从该端口读出该数据则通过函数void io_access_off( unsigned long port )释放对端口0x80和并口的控制权。
接下来调用函数
void SetPptCompMode(void)
//configure the parallel port at the compatibility mode.
ISnERRORINT | ECR_DISDMA | ECR_源文件中这个函数是设置并口的兼容模式,下面先看看并口的模式
下的并口模式:
种模式
在主板中BIOS 设置为EPP 或ECP 模式,故在软件
中就没函数中执行void JTAG_ReadId(void),在解释这个函数之前,先简要介绍一下JTAG 技术。主要包括4个部分(见图5)
{
//_outp(validPpt+ECP_ECR,ECR_STANDARD | ECR_D DISSVCINT);
}
在由于双向并口是各制造商独自设计没有一个统一的规范。逐渐形成了如1、原始并口SPP 单向8位+双向4位
2、简单双向PS/2 双向8位
3、增强并口EPP 高速双向
4、扩展并口ECP 高速双向可
5、多模式口ECP+EPP 可工作于多在该函数中的语句是被注释了的,因为一般有必要在设置了,公司介绍源码
如果你没有在主板BIOS 中设置,那就的去掉注释了,但现在主板默认是EPP 或ECP 模式的。
接下来回到主
JTAG
图5 JTAG 结构示意
(1)测试访问端口TAP(Test Access Port):JT :TDI(Test data in),TDO(Test data 。逻辑测试单元有自己的时钟(TCK)和复位以让你将测试指令和数据送入设备,将测试结果读出。测试器通过TCK 和TMS 控 制T 下,产生控制信号。其中一类是选链信号,的长度一般等于指令长度,指令通过TDI 逐位移入指令寄存器,AG 定义了4个基本端口out),TMS(Test model select),TCK(Test clock );分别实现测试数据的输入与输出,测试模式的选择以及提供测试时钟。此外,JTAG 还定义了一个可选端口TRST,用于实现测试复位,在具体的电路中可能没有用到TRST,如图1中,就没有设计TRST(Test  reset).
测试访问端口由五个专门引脚(四个输入和一个输出) 组成(TRST # ) 引脚,因此它独立于其他设备。既使其他设备处于复位状态或无电状态,逻辑测试单元可以读或写自己的寄存器。
逻辑测试单元可AP 控制器的操作。指令和数据由TDI 串行输送到TDO。
(2)TAP 控制器:TAP 控制器的作用是在TMS﹑TCK 和TRST 的作用即在测试数据寄存器组和指令寄存器之间进行选择的信号;另一类是扫描控制信号,控制着测试数据寄存器与指令寄存器进入相应的状态。
(3)指令寄存器及译码逻辑:指令寄存器在译码逻辑的作用下,产生译码信号。其产生的译码信号,主要有针对边界扫描单元的控制信号,以及在