在分析test_port()之前,我们首先对并口编程先进行一些介绍,我们的PC机一般有三个并口,他们的IO地址范围通常是:

0x3bc-0x3be

0x378-0x37a

0x278-0x27a

在很多电脑里面,通常连接Jtag的并口是以0x378为基地址的并口。

可以看到一个并口有三个IO地址,第一个是数据寄存器地址,第二个是控制寄存器地址,第三个是状态寄存器地址。

JTAG原理

上篇文章刚刚提到 test_logic_reset函数,这个函数是用来reset

Jtag链的,继续分析之前,还是先让我们来了解JTAG的工作状况。为了测试我们的PCB板的方便,JTAG这个东西被搞了出来。如果想更多的了解

JTAG,大家可以去看看IEEE 1149.1的标准,如果只是和我一样,想了解一下的话,大家可以看看Mark

Zwolinski著《VHDL数字系统设计》,电子工业出版社出版了他的中文版。

每一个JTAG兼容的元件都有一个共用的测试结构,这种结构基本单元如下:

1、测试存取端口

测试存取端口包括4个或5个为测试增加的引脚。这些引脚是:

TDI和TDO(测试数据输入和输出)。数据和指令通过扫描路径送至IC。没有办法从指令中区分数据,或者判断一系列位的目标是到达哪个特定的IC。因此,下面的引脚用来控制数据流向。

TMS(测试模式选择)。与TCK引脚一起,TMS引脚用来控制一个状态机以决定每位通过TDI到达目的地。

TCK(测试时钟)

TRST(测试复位),这是可选的异步复位信号,很多的JTAG电路中没有这个信号。

2、TAP控制器

TAP控制器是一个具有16个状态的状态机,它用来控制测试。状态机的输入是TCK和TMS,输出是其它寄存器的控制信号。下面链接是我在一个网站上找到的他的状态图,大家也可以在google的图片里面搜索tap

controller,就可以搜索到这个状态图。

 通过这个图可以看出,TMS脚上保持5个时钟周期的高电平,会使得状态机从任何状态进入Test-Logic-Reset。TAP控制器发出的控制信号用来启动器件中的其它寄存器。这样,如果到达TDI的位序列合适,就将被送到指令寄存器或者特别的数据寄存器。

3、测试数据寄存器(Test Data

Registers) 一个与边界扫描兼容的元件必须将其所有的输入和输出连接至扫描路径。一下描述的特殊单元用来实现扫描寄存器。另外,必须有一位的旁路寄存器,这样可以通过绕开元件的边界扫描寄存器来缩短扫描路径。另外还需要一些其他的寄存器,例如,一个IC可能需要一个标志寄存器,这个寄存器的内容可以通过扫描访问来确定

PCB板上是否装配了正确的IC。同样,我们可以通过边界扫描接口访问器件的内部扫描路径。某些可编程逻辑生产商允许使用边界扫描器件来对器件进行编程,因此,另一种可能的数据寄存器是配置寄存器。

4、指令寄存器(Instruction Register)

指令寄存器至少有2位,这依赖于实现的测试数目。它定义了测试数据寄存器的使用。指令寄存器还产生进一步的控制信号。

边界扫描单元有四种操作模式:

普通模式。一般的系统数据从In传输至OUT。

扫描模式。shfiterDR选择SCAN_IN引脚,ClockDR提供扫描路径时钟。ShifterDR值由Tap控制器中相似的名称的状态得来。当TAP控制器处于状态capture-DR或者shifter-DR时,断言ClockDR。

捕捉模式。ShiftDR选择In引脚,数据由ClockDR时钟送入扫描路径寄存器来对系统进行快照。

更新模式。在捕捉或者扫描之后,数依据通过UpdateDR一个时钟沿从左边沿触发送至OUT。

test_logic_rest函数分析

好,这里说了这么多的JTAG,下面我们继续分析源代码, test_logic_reset的代码如下:

void test_logic_reset(void)

{

putp(1,1,IGNORE_PORT);// keep TMS set to 1 force a test logic

reset

putp(1,1,IGNORE_PORT);// no matter where you are in the TAP

controller

putp(1,1,IGNORE_PORT);

putp(1,1,IGNORE_PORT);

putp(1,1,IGNORE_PORT);

putp(1,1,IGNORE_PORT);

}

这个函数的目的是用来对JTAG逻辑进行重置的,函数调用了6个putp函数。

putp函数源代码如下:

int putp(int tdi, int tms, int rp)

{

int tdo = -1;

// TMS is D2, TDI is D1, and TCK is D0, so construct an output by

creating a

// rising edge on TCK with TMS and TDI data set.

_outp(lpt_address, tms*4+tdi*2+8);// TCK low

_outp(lpt_address, tms*4+tdi*2+1+8);// TCK high

// if we want to read the port, set TCK low because TDO is

sampled on the

// TCK falling edge.

if(rp == READ_PORT)

_outp(lpt_address, tms*4+tdi*2+8);// TCK low

if(rp == READ_PORT)

tdo = !((int)_inp(lpt_address + 1) >>

7);// get TDO data

这里的代码是使用并口做JTAG访问的代码,可以看出,这个函数是产生一次TCK脉冲,同时发送数据和接受数据的。tdo最后返回的是TDO的状态值,使用了一个!是因为前面说过最高位的逻辑是与信号线上相反的。知道的putp代码的作用,我们就可以看出来,test_logic_reset的作用是让

TMS保持6个高电平,前面说过,TMS 5个电平就会使得器件进入重置状态。

jtag_test()函数分析

接下来,jtag_test()函数被调用,我们再来对他进行分析

void jtag_test()

{

// set all devices into bypass mode as a safe instruction

pre_IRSCAN();

if (controller_scan_code(COT_BYPASS, READ_PORT, CONTINUE) !=

0x1)

{

error_out("Jtag test failure. Check connections and

power.\n");

}

post_IRSCAN();

printf("JTAG Test Passed\n");

}

首先, pre_IRSCAN()被调用, pre_IRSCAN()的代码如下:

void pre_IRSCAN()

{

putp(1,0,IGNORE_PORT);//Run-Test/Idle

putp(1,0,IGNORE_PORT);//Run-Test/Idle

putp(1,0,IGNORE_PORT);//Run-Test/Idle

putp(1,0,IGNORE_PORT);//Run-Test/Idle

putp(1,1,IGNORE_PORT);

putp(1,1,IGNORE_PORT);//select IR scan

putp(1,0,IGNORE_PORT);//capture IR

putp(1,0,IGNORE_PORT);//shift IR

}

可以看出来,TAP状态机从Run_test/IDL到Selet_DR-Scan到Select-IR-SCAN再进入Capture-IR,最后进入Shift-IR,从函数返回的时候,器件进入等待数据移位进入IR的状态

然后,controller_scan_code函数被调用,该函数则完成将一个BYPASS指令移进IR当中,然后为什么会在TDO上得到一个高电平我就不清楚了,可能这是对BYPASS命令的应答。然后Post_IRSCAN被调用,状态机返回到Run-Test/Idle模式。

Jtag-test完成之后,就开始真正的flash烧写过程了

昨天分析到jtag_test了,今天继续往下看

char filename[MAX_IN_LENGTH];

if(argc >= 2)

strcpy(filename,argv[1]);

else

{

printf("enter file: ");

gets(filename);

}

程序接着检查了是否有指定文件名,如果没有,则获取文件名

test_logic_reset();

再次重置Jtag逻辑,使得系统进入可靠状态。

id_command();

执行id_command,该函数首先使TAP控制器进入ShiftIR状态,然后向IR中移入COT_IDCODE(0x1E)指令,然后使TAP控制器进入shiftDR状态,往TDI信号置1,将DR值移出来,与系统的ID想比较,如果相应,则函数执行成功返回,否则就打印错误信息,退出程序。

bypass_all();

接着bypass_all()被调用,该函数同样通过控制TAP控制器来向器件发送COT_BYPASS(0x1F)指令,使得器件进入bypass_all状态。

test_logic_reset()

接着继续调用test_logic_reset()使系统进入可靠状态。

check_rom_info(&max_erase_time,

&dsize, &max_write_buffer,

&block_size, &nblocks);

该函数调用了一连串的access_rom函数,access_rom函数是完成烧写的核心函数,时间已经晚了,明天继续分析

昨天分析到了check_rom_info函数,提到access_rom是整个的核心。

其实这么说也不大准确,应该说access_rom

是最底层操作的函数,它首先将TAP控制器状态移到ShiftDR,然后把准备好的各个引脚的电平状态设置好(没怎么搞懂高阻态是如何动作的,也许扫描链比实际引脚会多几个脚),移入扫描链中,然后把TAP控制器状态移到ShiftIR,把extest指令移入,使器件进入外部逻辑测试状态,刚才为扫描链中移入的电平就放到了引脚上。access_rom把参数addr放到器件的地址引脚上,把数据放到数据引脚上,同时把引脚原本的引脚信号移出TDO,就可以把flash返回在数据线上信号返回。

正如代码里面的那段注释:

To read data from the Flash Memory you must first fill the

processor JTAG chain with the Address, then pump the entire chain

out.however while pumping data out you can be pumping the next

cycle's Address in Therefore the JTAG chain looks like a pipeline,

valid read data always coming

out one cycle late.

当前flash返回的数据要下一次扫描的时候才能返回,所以access_rom函数返回的值是上次地址读到的数据。

check_rom_info的代码比较长,而且都是一些通过flash的CFI(Common Flash

Interface)对flash信息简单的读取操作,这里就不再贴出来了。

check_rom_info成功返回之后,程序开始检查将要写进flash的文件的合法性,主要是大小是否合法,如果比flash还大,就返回错误信息并退出。如果成功,经过一些简单的界面交互过程之后,程序开始调用test_lock_flash来检查相应的块是否已经被lock,如果被锁定,则发送命令将其unlock,然后返回之后,程序调用erase_flash和program,函数同样是使用acess_rom调用来在flash引脚上产生相应的时序来完成相应的操作。大家可以参考相应的flash芯片的资料。

最后,程序再把flash里面的数据读取出来进行与文件进行验证,检查烧写是否成功。

jflash烧录教程_Jflash烧录(windows)原理分析相关推荐

  1. xposed hook java_[原创]Android Hook 系列教程(一) Xposed Hook 原理分析

    章节内容 一. Android Hook 系列教程(一) Xposed Hook 原理分析 二. Android Hook 系列教程(二) 自己写APK实现Hook Java层函数 三. Androi ...

  2. jflash烧录教程_Jlink烧录nand flash操作(步骤一)

    一.将内存初始化程序下载至SRAM并运行 1.打开J-Link Commander,将micro开发板拨至nand flash启动. 2.以下是常用命令: speed 12000:设置下载速率为12M ...

  3. [置顶] 【稀饭】react native 实战系列教程之热更新原理分析与实现

    很多人在技术选型的时候,会选择RN是因为它具有热更新,而且这是它的一个特性,所以实现起来会相对比较简单,不像原生那样,原生的热更新是一个大工程.那就目前来看,RN的热更新方案已有的,有微软的CodeP ...

  4. react native 实战系列教程之热更新原理分析与实现

    很多人在技术选型的时候,会选择RN是因为它具有热更新,而且这是它的一个特性,所以实现起来会相对比较简单,不像原生那样,原生的热更新是一个大工程.那就目前来看,RN的热更新方案已有的,有微软的CodeP ...

  5. 【IAP】STM32和GD32的IAP原理分析、教程、资料整理

    文章目录 前言 一.什么是IAP? 二.IAP执行原理(以STM32F10X为例) 2.1 STM32F10X的储存器映像 2.2 正常上电的运行流程 2.3 加入IAP后的Bootloader运行流 ...

  6. marlin固件烧录教程_小白穿越机教程-刷固件 | 穿越机如何刷最新的betaflight固件教程...

    关注公众号[FPV One],用最酷的姿势玩穿越机✈️ 哈喽,大家好,我是小哥! (这是一期系列教程,我会从原理,部件,组装,调参,飞行技巧等几个方面来介绍新手如何入门穿越机.) 往期精彩内容,别错过 ...

  7. Air780E烧录教程

    目录名称 LuaTools 简介 环境 LuaTools 安装 LuaTools 功能介绍 烧录固件 视频烧录教程 LuaTools 简介 Luatools是合宙提供的单机版调试工具,支持最新固件获取 ...

  8. 树莓派3 Ubuntu Meta16.04 操作系统烧录教程及系统换源

    树莓派3 Ubuntu Meta16.04 操作系统烧录教程及系统换源 1 写在开头: 2 操作系统烧录软件下载 3 Ubuntu Meta 操作系统下载 4 操作系统烧录 4.1 SD 存储卡格式化 ...

  9. php 实现自动加载更多,$.ajax+php实战教程之下拉时自动加载更多文章原理分析二...

    摘要: 继上一篇<$.ajax+php实战教程之下拉时自动加载更多文章原理分析>文章进行进一步讲解,完善之前的代码及引入ajax和php相关内容...... 上次留下的问题不知道看官们有没 ...

  10. Arduino框架下STM32F1/F4系列HID模式程序烧录教程

    Arduino框架下STM32F1/F4系列HID模式程序烧录教程 相关篇<Arduino框架下STM32全系列开发固件安装指南> HID BootLoader烧录模式 "Upl ...

最新文章

  1. 顺序表-顺序表的基本操作(插入元素+删除元素)
  2. 计算机视觉的“惨胜”:反思大型图像数据集
  3. python实现阿里云域名绑定动态IP
  4. c++ 32位有符号的整数_【LeetCode】字符串分类字符串转换整数 (atoi)
  5. 028 -bash-4.1$ 出现故障的原理及解决办法?
  6. [评论]为什么程序员的社会地位不高?--转载
  7. android放微信@功能,Android仿微信语音消息的录制和播放功能
  8. w10系统桌面的计算机找不到,w10桌面我的电脑图标不见了怎么办
  9. react 学习之Protal
  10. 雷神simplest_ffmpeg_player解析(一)
  11. matlab信号时序图,怎么看时序图,电路原理图(转)
  12. 关于技术型人才与研究型人才
  13. SIGGRAPH Asia 2022 | 港中文MMLab:Marker Correspondence估计框架和应用
  14. brpc源码分析——数据报处理过程
  15. 群签名和Go语言实现细节(BBS04--Short Group Signatures)
  16. Mockito单元测试-answer
  17. (二)第一步(安装和基本使用) | 普罗米修斯(Prometheus)
  18. 河南省天一大联考2021高考成绩查询,河南省2019天一大联考高三五联H成绩新鲜出炉,本科分数线公布!...
  19. Linux编写c程序计算圆的面积,c语言如何计算圆面积和周长
  20. 南京师范大学计算机技术研究生就业,南京师范大学计算机技术在职研究生怎么样?...

热门文章

  1. linux so库反编译命令,使用IDA反编译.so文件并修改
  2. 最新版盲盒商城thinkphp+uniapp
  3. matlab数学建模试卷,matlab数学建模习题
  4. tkinter教程_Tkinter教程–第2部分
  5. 联想笔记本linux驱动,联想为Linux驱动的计算机提供自动固件更新
  6. 网络热门知识点,Linux内核——网络协议栈基本知识
  7. VisualStudio2017密钥(key)
  8. gpgga格式读取MATLAB,GPS协议GGA、GLL、GSA、GSV、RMC、VTG解释
  9. 热传导方程以及Matlab求解
  10. 基于激光雷达的3D实时车辆跟踪