blavince's BLOG

Giving is a reward in itself.

0%

C# 控制 Sparkfun Bus Pirate - v3.6a (通用總線接口設備)

嵌入式開發時為了各種驗證, 通常都得花時間從代碼面實現; 但如果能直接產生訊號與晶片通訊或者能直接解析晶片發出的訊號, 那開發跟除錯時就有更多操作空間了. 研究由 sparkfun 發起的 Bus Pirate - v3.6a 專案和產品, 同時他們也提供開源資源.

介紹

腳位定意圖:

最常見的晶片通訊協定如: UART, I2C 和 SPI 它都有支援, 但 Host 端電腦需要安裝 FT232RL USB-to-Serial 晶片的驅動程式 (通常插上後 Windows 會自動安裝, 也可自行上網找安裝檔).

產品支援兩種使用方式:

  1. User terminal mode
  2. Binary scripting mode

預設為第一種 1. User terminal mode, 而第二種 2. Binary scripting mode 是方便我們送出一些特定 byte 寫程式控制它. 以下分別介紹這兩種模式, 更多介紹可以參考官方說明文件 Bus Pirate v3.6a Hookup Guide.

1. User terminal mode

接上 Bus pirate 後, 使用任何一個終端機軟體 ( 如: Tera Term ) 開啟 Serial Port 後

  1. 點擊 setup
  2. 點擊 Serial port…
  3. 確定 speed 為 115200
  4. New setting
  5. Console 鍵入 Enter 出現提示符 Hiz>

輸入 ? 可以看所有介紹

參考 Saleae Logic 8 邏輯分析儀 內關於 SPI 通訊標準, 以下步驟 1~6 設置 SPI 參數,

就可以輸入 SPI 需要的 frame, 如: _-_0x20 0x00 0xar_ 依序送出 0x20, 0x00, 0x0a 與 dummy read.

2. Binary scripting mode

根據官方的說明文件, 我們只要連續送出不多於 20 次 0x00 的資料給 bus pirate 就會強制進入 Binary mode. 進入 Binary mode 後連續讀取 5 個 byte 可以得到 BBIO1.

1
2
3
4
5
6
7
8
9
10
11
private enum busPirateCmd
{
_BBIO1 = 0x00, //Enter reset binary mode
_SPI1 = 0x01, //Enter binary SPI mode
_I2C1 = 0x02, //Enter binary I2C mode
_ART1 = 0x03, //Enter binary UART mode
_1W01 = 0x04, //Enter binary 1-Wire mode
_RAW1 = 0x05, //Enter binary raw-wire mode
RESET = 0x0F, //Reset Bus Pirate
STEST = 0x10, //Bus Pirate self-tests
}

引用 C# 的 Serial

1
using System.IO.Ports;

宣告並開啟 serial port

1
2
3
4
5
6
7
//設定 Serial Port 參數
private SerialPort g_serialPort;
g_serialPort.PortName = COM7;
g_serialPort.BaudRate = 115200;
g_serialPort.DataBits = 8;
g_serialPort.StopBits = StopBits.One;
g_serialPort.Open();

寫入 0x00

1
2
3
Byte[] buffer = new Byte[1];
buffer[0] = Convert.ToByte(busPirateCmd._BBIO1);
g_serialPort.Write(buffer, 0, buffer.Length);

成功進入 Binary mode, 接著對齊上節 SPI 設置, 送出 0x01 進入 SPI mode (進入後可讀回 4 個 byte: SPI1 ) 後設置相關參數如下,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private enum peripheralsCfg
{
powerOn = 0x08,
pullUps = 0x04,
AUX = 0x02,
CS = 0x01,
}

private enum spiSpeed
{
_30KHZ = 0x00,
_125KHZ = 0x01,
_250KHZ = 0x02,
_1MHZ = 0x03,
_2MHZ = 0x04,
_2_6MHZ = 0x05,
_4MHZ = 0x06,
_8MHZ = 0x07
}

private enum spiCfg
{
OUT_TYPE = 0x8,
IDLE = 0x4,
CLK_EDGE = 0x2,
SAMPLE = 0x1
}

private enum csCfg
{
CSLow = 0x02,
CSHigh = 0x03,
}

說明文件提示個別參數有其前綴 byte 如下 (0x40, 0x60 和 0x80), 於序列阜寫入以下,

1
2
3
4
5
6
Byte[] buffer = new Byte[4];
buffer[0] = Convert.ToByte(0x40 | (byte)peripheralsCfg.powerOn);
buffer[1] = Convert.ToByte(0x60 | (byte)spiSpeed._250KHZ);
buffer[2] = Convert.ToByte(0x80 | (byte)spiCfg.OUT_TYPE);
buffer[3] = Convert.ToByte((byte)csCfg.CSHigh);
g_serialPort.Write(buffer, 0, buffer.Length);

然後第一個 frame 需要預告後續在 SPI bus 上寫入多少個 frame, 如: 0x13 就是 4 個 frame 的意思,

1
2
3
4
5
6
7
8
g_serialPort.ReadExisting();
Byte[] buffer = new Byte[5];
buffer[0] = Convert.ToByte(0x13);
buffer[1] = Convert.ToByte(0x20);
buffer[2] = Convert.ToByte(0x00);
buffer[3] = Convert.ToByte(0xF0);
buffer[4] = Convert.ToByte(0xF0);
g_serialPort.Write(buffer, 0, buffer.Length);