iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 24
0

0. 前言

上篇簡單的介紹後,本篇將深入介紹MPSSE中,常用到的Command,
作為下一篇實作部分的引導!

本文預計主要分成以下小節:

  • Initial & Configure Commands
  • JTAG Control
    • LSB Data In/Out Commands
    • TMS Out Commands

以上部分用來分別探討,從初始化開始到常用的TDI、TDO、TMS等訊號處理的Commands
  
  
  

1. Initial & Configure Commands

由於FT2232晶片中其實沒Register等東西需要設定,初始化的方式也很簡單,
傳幾個Commands把需要的東西打開/關閉,讓他可以在指定的功能下使用!

底下分成幾個小節分別說明這些部分!
  
  

1.1 Set Data bits(High Byte/Low Byte)

一般在初始化的時候,必要設定每根訊號線的初始值及訊號線的方向(Input/Output),
在MPSSE中會將16根訊號線拆成High Byte、Low Byte兩組,然後利用各自的Command設定初始值(Value)及方向(Direction)

  • 0x80, 0xValue, 0xDirection: 設定Low Byte那組的Value及Direction
  • 0x82, 0xValue, 0xDirection: 設定High Byte那組的Value及Direction
    Direction中,1表示為Output

例如:

我希望將這16根訊號線的初始值(Value)設定為0x0808(LSB對應GPIO 0、MSB對應GPIO 15)和方向(Direction)設定為0x0a1b,則使用下面兩組Commands:
"0x80, 0x08, 0x1b" 和 "0x82, 0x08, 0x0a"

轉換的方式如下:

0x0808 = (0000 1000 0000 1000)
0x0a1b = (0000 1010 0001 1011)

對應到Pin上:

Pin # Value Direction
ADBUS0 0 1
ADBUS1 0 1
ADBUS2 0 0
ADBUS3 1 1
ADBUS4 0 1
ADBUS5 0 0
ADBUS6 0 0
ADBUS7 0 0
ACBUS0 0 0
ACBUS1 0 1
ACBUS2 0 0
ACBUS3 1 1
ACBUS4 0 0
ACBUS5 0 0
ACBUS6 0 0
ACBUS7 0 0

表示其中ADBUS3、ACBUS3初始值為1,
而且ADBUS0、ADBUS1、ADBUS3、ADBUS4、ACBUS1、ACBUS3皆為Output!
  
  

1.2 Clock Divisor

當然,作為一個USB和JTAG溝通之間的橋梁,不免俗的一定要有Command來控制Adapter出TCK的速度!

首先介紹一下FT2232H中,Clock的計算方式:

在FT2232H中內部預設使用的頻率是60 MHz,計算方式如下!

https://ithelp.ithome.com.tw/upload/images/20180111/201073279epbF3Xopd.png

其中,ValueH、ValueL為使用者設定的部分,主要是將原先的除數分成前8-bits的ValueH和後8-bits的ValueL!

為了相容於前版的FT2232D中使用的12 MHz,因此在FT2232H中而外提供指令將原先頻率先除頻(Frequency divider)變成12 MHz,因此計算方式也可以變成如下所示!

https://ithelp.ithome.com.tw/upload/images/20180111/20107327R4sF3ioIqb.png

以下是Value和頻率對應的關係:

Value 60 MHz max TCK 12 MHz max TCK
0x0000 15 MHz 3 MHz
0x0001 10 MHz 2 MHz
0x0002 7.5 MHz 1.5 MHz
....
....
0xFFFF 457.763 Hz

因此在這邊介紹兩組共三個MPSSE Command!
第一組是除頻器的開關(Clk Divide by 5):

  • 0x8A: 關閉除頻器,預設使用的CLK為60 MHz
  • 0x8B: 開啟除頻器,將使用的CLK降至12 MHz

第二組則是負責設定Value的MPSSE Command:
0x86, ValueL, ValueH: 負責設定CLK的除數(Divisor),輸出指定的TCK
  
  

1.3 Loopback

FT2232H中,提供一個自我測試的功能,讓TDI可以接回TDO中,測試TDI傳輸和TDO接收是否正常:

  • 0x84: 開啟Loopback
  • 0x85: 關閉Loopback

不過由於我們在JTAG中基本上是不需要用到Loopback,所以一般在初始化階段中,會送"0x85"將這個功能關閉!
  
  

1.4 RTCK(Adaptive clocking)

最後介紹一個特殊的應用:
當如果不需要使用Adapter中的TCK功能時,可以利用Target端傳過來的RTCK作為同步用!

這部分應用比較特殊,OpenOCD中在支援這功能時也有特殊限制,詳細內容可以參考: 「FAQ 2. RTCK, also known as: Adaptive Clocking - What is it?

在這邊介紹一下FT2232H中支援這個功能的開關:

  • 0x96: 開啟RTCK功能
  • 0x97: 關閉RTCK功能
      
      
      

2. JTAG Control

JTAG訊號的控制,只要分成TCK、TDI、TDO和TMS等四根,
其中TCK由Adatper控制外,剩餘三根的資料進/出、資料長度、資料內容等等,
則全交由使用者自行決定,因此在MPSSE Command中,編碼主要有以下的規則:

  • Bit 0: 在CLK Falling edge(-VE CLK)時,送出TDI/TMS!? (1:Yes / 0: No)
  • Bit 1: 資料為bit/byte模式 (1: Bit mode / 0: Byte mode)
  • Bit 2: 在CLK Falling edge(-VE CLK)時,從TDO接收資料!? (1:接收 / 0:不接收)
  • Bit 3: LSB/MSB優先傳輸? (1: LSB / 0: MSB)
  • Bit 4: TDI傳輸? (1:傳輸 / 0:不傳輸)
  • Bit 5: 從TDO接收資料? (1:接收 / 0:不接收)
  • Bit 6: TMS傳輸? (1:傳輸 / 0:不傳輸)
  • Bit 7: 保持0

由於在JTAG中規定,資料必須由LSB優先傳輸,因此我們只需要考慮Bit 3為1的那些Command,
請參考下節內容!

2.1 LSB Data In/Out Commands

以下Command皆是由LSB開始發送,請參考以下Command Table:

OPCODE Read TDO? (Bit 5) Write TDI? (Bit 4) -VE CLK Read? (Bit 2) Bits? (Bit 1) -VE CLK Write? (Bit 0)
0x18 - YES - BYTES +VE
0x19 - YES - BYTES -VE
0x1A - YES - BITS +VE
0x1B - YES - BITS -VE
0x28 YES - +VE BYTES -
0x2C YES - -VE BYTES -
0x2A YES - +VE BITS -
0x2E YES - -VE BITS -
0x39 YES YES +VE BYTES -VE
0x3C YES YES -VE BYTES +VE
0x3B YES YES +VE BITS -VE
0x3E YES YES -VE BITS +VE

不過在JTAG中,當TCK上升(+VE CLK)時,
TDI資料應該就已經要先準備好等待寫入,因此只需要考慮"-VE CLK Write"、"+VE CLK Read"的那些Command!

所以可以將這個Table簡化成下面的部分:

OPCODE Read TDO? (Bit 5) Write TDI? (Bit 4) -VE CLK Read? (Bit 2) Bits? (Bit 1) -VE CLK Write? (Bit 0)
0x19 - YES - BYTES -VE
0x1B - YES - BITS -VE
0x28 YES - +VE BYTES -
0x2A YES - +VE BITS -
0x39 YES YES +VE BYTES -VE
0x3B YES YES +VE BITS -VE

以下拆成三組來介紹:

  • 純寫TDI
  • 純讀TDO
  • 寫TDI,並讀TDO

  
  
首先是純寫TDI的部分:

  • 0x19, LengthL, LengthH, Byte1, ....... , Byte65535: 從Byte1的LSB開始依序在-VE CLK的時候,從TDI送出,總共送出(LengthH | LengthL)+1個Byte (*註1)
  • 0x1B, Length, Byte: 從LSB開始,在-VE CLK的時候,從TDI送出,總共送出Length+1個Bits

(*註1) 參考下圖範例:

https://ithelp.ithome.com.tw/upload/images/20180111/20107327FBh6LFKd2f.jpg

  
  
再來是純讀TDO的部分:

  • 0x28, LengthL, LengthH: 在+VE CLK的時候,依序從LSB開始讀取,共(LengthH | LengthL)+1個Byte
  • 0x2A, Length: 在+VE CLK的時候,依序從LSB開始讀取,共Length+1個Bits

  
  
最後是同時讀寫的部分:

  • 0x39, LengthL, LengthH, Byte1, ....... , Byte65535: 在+VE CLK的時候送出;在-VE CLK的時候讀取;以Bytes為單位
  • 0x3B, Length, Byte: 在+VE CLK的時候送出;在-VE CLK的時候讀取;以Bits為單位
      
      

2.2 TMS Out Commands

這部分主要使用以下兩種Command:

  • 0x4B, Length, Byte1: 從Byte1的LSB開始,依序將0~Length+1個Bit,在-VE CLK的時候,寫入TMS中!
  • 0x6B, Length, Byte1: 從Byte1的LSB開始,依序將0~Length+1個Bit,在+VE CLK的時候,寫入TMS中,並在-VE的時候從TDO中讀取資料

注意: 這邊有個小小"tricky"的地方,就是Byte1的Bit 7在TMS開始傳輸前,「會被放到TDI上
  
  

2.3 Execution

最後,當然要介紹一下這些Command送到FTDI晶片中時,要怎麼執行,
很簡單,就是送一個0x87: Send Immediate指令就行了!

他會將晶片中的Buffer整個送出到Target端,並將結果送回PC中!
  
  
  

99. 結語

FTDI整本文件約莫30頁,不過實際應用到的部分就是那幾個,
難的是如何應用這幾個Commnads完成JTAG、TDI、TDO、TMS等訊號的控制,
並將資料回傳至上層!

明天的文章中,將作本系列最後的總結: 探討OpenOCD中如何支援MPSSE,將上層的JTAG Commands轉成對應的MPSSE Command,並支援FTDI-based Debug Adapter從初始化、設定到傳送JTAG Commands等等功能的實作和背後的秘密!

如果真的解釋沒很清楚,歡迎留言 (含金量高!?)
  
  
  

參考資料

  1. FT2232H Dual High Speed USB to Multipurpose UART/FIFO IC Datasheet Version 2.5
  2. AN_108 Command Processor for MPSSE and MCU Host Bus Emulation Modes

上一篇
Day 23: 您不可不知的FT2232H (1/3) - Overview
下一篇
Day 25: 您不可不知的FT2232H (2.5/3) - MPSSE Initial
系列文
系統架構秘辛:了解RISC-V 架構底層除錯器的秘密!30

尚未有邦友留言

立即登入留言