Saleae
一、前言
? ? ? ?最近這家公司正在開發一款新產品,經常需要通過Saleae 邏輯分析儀抓取二進制數據,然后經過解析,再轉換成16進制,再根據通訊協議對數據進行相關處理。邏輯分析儀官方自帶解碼器,所以解析二進制波形非常簡單。但是,對于一些特定的編碼方式有非常多種,所以沒有官方提供相應的解碼器,因此需要手動計算每個波形的,然后再轉換成對應的二進制位,再將每個bit 轉換為16進制byte ,所以,這非常的麻煩和累,并且非常容易出錯。
? ? ? ? ?所以,要根據邏輯分析儀的官方提供的SDK ,進行二次開發,開發我們需要的自定義解碼器,翻遍度娘發現相關資料少之又少,幾乎沒有講解這個該從何做起。由于之前完全沒有接觸過這方面的東西,因此,有了這篇文章。記錄我是怎么從0 開始,編寫一個自定義解碼器。
二、相關資料
1. Saleae 邏輯分析儀
1.1 邏輯分析儀
是分析數字系統邏輯關系的儀器。邏輯分析儀是屬于數據域測試儀器中的一種總線分析儀,即以總線(多線)概念為基礎,同時對多條數據線上的數據流進行觀察和測試的儀器,這種儀器對復雜的數字系統的測試和分析十分有效。邏輯分析儀是利用時鐘從測試設備上采集和顯示數字信號的儀器,最主要作用在于時序判定。由于邏輯分析儀不像示波器那樣有許多電壓等級,通常只顯示兩個電壓(邏輯1和0),因此設定了參考電壓后,邏輯分析儀將被測信號通過比較器進行判定,高于參考電壓者為High,低于參考電壓者為Low,在High與 Low之間形成數字波形。
1.2 采樣深度
即對被測信號一次采集的樣點總數。它直接決定了一次采樣所能采集到的數據量的多少,顯然深度越大,一次采集的數據量越大。
1.3 采樣率(Sample Rate)
采樣率也稱采樣速率,即對被測信號進行采樣的頻率,也就是每秒所采集的樣點數。它直接決定了一次采樣結果的時間精度,采樣率越高,時間精度越高。一次采樣結果的時間精度就等于“1/采樣率”,即一個采樣周期。
1.4 采樣時間
一次采樣過程所持續的時間等于“采樣深度÷采樣率”,即:
采樣時間 = 采樣深度 / 采樣率.
三、Saleae SDK 開發
3.1 官網介紹:
The Saleae Analyzer SDK lets you make your own custom protocol analyzers. The framework is very flexible. You can do everything we can do (we use the same SDK). You'll be creating a shared library (.dll, .so, or .dylib) that will be loaded by the Logic software as a plugin.
While there are many advantages to providing the SDK in this format, implementation of a custom protocol will probably take an experienced C++ developer at least a full day, and possibly up to a week, to complete. You will probably want to have had considerable programming experience, probably significant C++ experience, before taking it on.
That said, you can get away with implementing only a small part of the full capability of the analyzer. For example, you could have only one setting (the input channel(s) to use), and you could skip creating simulated data to test against, not bothering to provide for data export or tabular display.
Further, by default, you will start out with a fully featured and maximally simple analyzer—SimpleSerialAnalyzer. The documentation will walk you through how to modify it to suit your needs, as well as what parts can be left empty.
SDK 官網地址:?Protocol Analyzer SDK? ?
上面簡單的意思是說,
Saleae Analyzer SDK 可以制作自己的自定義分析器Analyzer。該框架非常靈活,官方的分析器也是使用相同的 SDK編寫出來的。解碼器Analyer 是共享動態庫(.dll、.so 或 .dylib),該庫將由 Logic 軟件以插件形式加載。 自定義協議的實現可能需要有經驗的 C++ 開發經驗,一開始不了解SDK 和 SDK中的API, 可以只實現Analyer 的一小部分功能,然后再進行復雜的擴展。 可以從官網提供的,功能齊全且極其簡單的分析器開始學習——SimpleSerialAnalyzer 并且有文檔將指導如何修改它以滿足需要. 最新 SDK 版本下載地址: Sample Analyer on Github Analyer SDK on GitHub2. 工程構建
2. 1. 根據官網指南,總的分為3步
a.?創建自定義分析器工程? ?b.?構建自定義分析器? ?c.?編譯和調試自定義分析器
2.2.1?創建自定義分析器工程, 參考官網:
?Setup - Analyzer SDK?
2.2.2 構建自定義分析器? ??參考:
官網鏈接 - ?Build - Analyzer SDK ??
?Build - Analyzer SDK?
2.2.3 編譯和調試自定義解密器 參考官網:
Debug - Analyzer SDK?
上面每個步驟官網都有詳細描述,需要注意的是,構建分析器時,根據不同平臺(x86 和 x64 ),使用不同配置.
關于調試自定義分析器,根據官網提示,在Logic v1.1.18 之后的軟件是不支持將自定義分析器附件到軟件上,
即,v1.1.18 之后的軟件在開發自定義分析器的時候,無法進行斷點調試。
如果實在需要進行斷點調試,必須要是舊版的 1.1.14 SDK + Logic v1.1.18 Windows 32 獨立版本 才能進行斷點調試。
注意: ?Logic v1.1.18 是32位, 只能調試x86 版本的dll, 并且只能對 1.1.14 SDK 配合進行斷點調試,不能用于最新版的sdkti調試如果連接最新版的SDK, 則會提示 ?"Unable to 'LoadLibrary' on dll ... is not a valid Win32 application" 。
舊版 1.1.14 SDK 下載地址:
Saleae Analyzer SDK 1.1.14 (包括用戶指南) ?
?Saleae Analyzer Source Code 1.1.14 (包含所有分析器代碼)?
確保SDK只編譯 32 位,因為 1.1.14 SDK 是在 Saleae 開始針對 64 位 Windows 之前發布的。
這也是為什么需要 1.1.18 軟件的 32 位獨立版本的原因。
因此,需要進行SDK 斷點調試,只能使用 舊版的 1.1.14 SDK + Logic v1.1.18 Windows 32 獨立版本.
3. 工程目錄說明(與官方Sample 例程說明)
3.1 AnalyzerSDK:
存放 Saleae SDK 的目錄,直接在官網下載后,將Saleae SDK 目錄下所有文件拷貝到該目錄即可。
3.2 docs
? 存放Saleae Analyzer SDK 開發文檔 等。
?3.3 LegacyAnalyzerSDK
?舊版SDK 存放目錄
3.4 source
工程源代碼存放目錄
4. Saleae 相關類
4.1 SimpleSerialAnalyzer.cpp 和?SimpleSerialAnalyzer.h
這兩個文件主要包含分析器主要部分,由分析器派生的類是分析器的核心。這里個類,可以實時分析和解析波形圖,并生成需要的結果.
4.1.1?SimpleSerialAnalyzer API 說明
4.1.1.1 void {YourName}Analyzer::WorkerThread()
WorkThread這個函數是所有東西的關鍵,在這里你將獲取波形數據,開始解碼,并且保存.
4.1.1.2 bool {YourName}Analyzer::NeedsRerun()
一般來說,只要在這個函數中返回false.
4.1.1.3 U32 {YourName}Analyzer::GenerateSimulationData( U64 minimum_sample_index, U32
device_sample_rate, SimulationChannelDescriptor** simulation_channels )
這個函數主要用于,被調用來獲得模擬數據的函數, 主要在舊版 1.1.14 和 Logic 1.1.18 附加調試時使用,主要調用SimpleSerialSimulationDataGenerator 這個類的函數,為WorkThread, 在附加調試時,提供模擬數據, 其中模擬波形數據是人為生成的.
4.1.1.4 U32 SerialAnalyzer::GetMinimumSampleRateHz()
提示用戶采樣需要的最小采樣速率,一般根據實際需要返回.
4.1.1.5 const char* {YourName}Analyzer::GetAnalyzerName() const
需要返回,在“添加分析工具”下拉列表中看到的名稱.
4.1.1.6 const char* GetAnalyzerName()
跟GetAnalyzerName() ?返回一樣的字符串即可.
4.1.1.7 Analyzer* CreateAnalyzer()
返回一個指向分析器派生類的新實例的指針.
4.1.1.8 void DestroyAnalyzer( Analyzer* analyzer )
只需在所提供的指針上調用刪除項即可.
4.1.1.9?void SetupResults()
設置結果集,其中,
void SimpleSerialAnalyzer::SetupResults() {//1. 創建一個分析器結果集對象, 并將用戶的設置參數傳入mResults.reset( new SimpleSerialAnalyzerResults( this, mSettings.get() ) );//2. 將結果集對象放置到 分析器對象中SetAnalyzerResults( mResults.get() );//3. 設置需要在哪個通道上顯示通過氣泡顯示數據mResults->AddChannelBubblesWillAppearOn( mSettings->mInputChannel ); }4.1.1.10?AnalyzerChannelData*?GetAnalyzerChannelData( Channel inputChannel)
獲取指定通道的波形數據本身,就是采樣的數據.
4.1.1.11?U32?GetSampleRate(void)
獲取當前邏輯分析儀采樣速率.
4.1.1.12??BitState 位狀態
在Saleae SDK 中,經常使用的一種類型,表示一個通道的口號狀態,狀態有兩個,??BIT_LOW or BIT_HIGH。
BIT_LOW? 表示下降沿, 電平變化由 高 -> 低
BIT_HIGH? 表示上升沿,電平變化由 低 -> 高。
4.1.2 AnalyzerChannelData
解析選定通道采集到的數據,AnalyzerChannelData?是一個可以訪問Saleae采集到數據的類。Saleae 以序列化數據流的形式提供數據,數據的訪問不會“隨機訪問”所保存的數據中的任何一個bit。相反,而是從數據的開始按順序訪問,并隨著訪問更多可用的數據而繼續前進(Advance)或移動,直到一輪數據訪問完畢。
4.1.2.1?AnalyzerChannelData - State
AnalyzerChannelData 類相關API
4.1.2.2?U64 GetSampleNumber(void)
獲取當前采樣數據的位置
4.1.2.3 BitState GetBitState(void)
獲取當前某個位置對應的電平狀態
在AnalyzerChannelData 是每個采樣點都有一個Number記錄著表示前進(Advance)或移動的位置,要在進行數據流訪問時,想知道當前在整個數據流的位置時,可以使用?GetSampleNumber() 這個函數, 需要獲取當前位置對應的電平,可以使用GetBitState() 函數。
4.1.3?AnalyzerChannelData – Basic Traversal?
采樣數據流的基本遍歷訪問,在數據流中前進或移動時,需要用到一些API.
4.1.3.1 U32 Advance( U32 num_samples )
這個函數作用時在整個樣本數據流中前進移動,前進移動num_samples個樣本,此函數將返回輸高低電平切換次數(從高到低,或從低到高).
這樣子解釋可能晦澀難懂,我剛才開始也是難以理解。簡單來說,Saleae 邏輯分析儀采集到的數據是數據流來的,每個采樣點對應一個高低電平信號,并且每個采樣點,都有sample 記錄著 它在數據流中的位置。而這個位置是可以向前移動的,怎么樣移動呢? 就是調用這個Advance 這個函數實現,移動樣本數量(即: 采樣點的個數) 就是 num_samples 這個參數。
4.1.3.2 U32 AdvanceToAbsPosition( U64 sample_number )
函數的功能是,前進移動到采樣到數據流中的某個絕對位置,它還將返回在移動過程中更改的輸入的次數。這個函數是移動到指定樣本的位置,sample_number 是樣本編號,即樣本的地址,表示第幾個樣本。
4.1.3.3 void AdvanceToNextEdge()
移動到下一個邊沿, 即電平變化的位置,此時可以通過GetSampleNumber(), 獲取當前進到樣本的位置.
4.1.4?AnalyzerChannelData – Advanced Traversal (looking ahead without moving)
高級遍歷樣本數據API.
4.1.4.1?U64 GetSampleOfNextEdge(void)
獲取下一個邊沿變化的樣本位置,此函數不會移動在流中的位置。記住,不能在流中向后移動,所以有時不移動就看到前面的東西是非常重要的。
4.1.4.2?bool WouldAdvancingCauseTransition( U32 num_samples )
移動num_samples 個樣本,函數不會移動在流中的位置。在這里,可以發現向前移動給定數量的樣本是否會導致位狀態(低或高)發生變化。
4.1.4.3?bool WouldAdvancingToAbsPositionCauseTransition( U64 sample_number );
移動到指定位置,函數不會移動在流中的位置。
4.1.5 Filling in and saving Frames?
上面講述的是怎么解析數據,這里講述如何保存數據,在Saleae 保存數據的基本單位是Frame,每個數據保存都在Frame? 實例化對象中。
4.1.5.1 Frame frame;
frame.mStartingSampleInclusive;? ?//記錄幀在樣本流中的開始位置
frame.mEndingSampleInclusive ;?//記錄幀在樣本流中的結束位置
frame.mData1;? //幀有效數據1
//frame.mData2;? //幀有效數據2
//frame.mType? ? ? ? ? ? ? ?//數據類型??
frame.mFlags ;? ? ? ? ? ? ? ? //標識
一般的,在幀解析中,一般mData1 和 mData2 用來保存有效數據,不一定所有都要用到,mType 和 mFlag 標識幀的類型,這兩個都可以自定義,mStartingSampleInclusive 和?mEndingSampleInclusive 這兩個記錄在樣本流中的位置,主要用于當需要在Logic 軟件顯示數據時,數據氣泡的開始位置和結束位置.? 而且,?mStartingSampleInclusive? 必須大于?mEndingSampleInclusive。
4.1.5.2 void AddMarker( U64 sample_number, MarkerType marker_type, Channel& channel )
主要用于標記幀的位置,或者在數據流中添加標記。
4.2?SimpleSerialAnalyzerSettings.cpp 和?SimpleSerialAnalyzerSettings.h
這個使用在Logic 軟件中提供給用戶界面上,設置分析器需要用到的參數。至少有一個參數,用于選定需要輸入數據的通道。
變量類型可以是任何你喜歡的類型——字符串、雙變量、int、枚舉等等。請注意,這些變量需要序列化(稍后保存到文件),因此如果有疑問,請堅持使用簡單類型(而不是自定義類或結構)。SDK提供了一種序列化和存儲變量的方法。
4.2.1?SimpleSerialAnalyzerSettingsAPI 說明
關于各個API 這個很簡單,可以去看官方說明文檔,不需要過多解釋。
4.3?SimulationDataGenerator.cpp 和?SimulationDataGenerator.h
這個類主要生成仿真數據,即模擬邏輯分析儀接收的數據。生成可控的、可預測的波形來測試WorkThread中的分析器代碼。通常應該使模擬數據與用戶設置匹配,因此可以在各種預期條件下進行測試。此外,模擬數據為最終用戶提供了一個在使用分析器時會發生什么的示例,以及波形應該是什么樣的示例。
值得注意的是,我在調試代碼過程中,多次實驗和總結:
這個類只有在Saleae SDK 版本位 1.1.14 和 Logic.exe 1.1.18 才能用到,在新版的由于新版的SDK 不支持 Logic 1.1.18 的在線調試,所以不能使用,而新版本的Logic.exe 不支持SDK附加調試,因此。只能用于 Saleae SDK 1.1.14 和 Logic 1.1.18 win32 才能使用,在x64 都不能使用。
如,模擬波形
4.3.1 一些概念
4.3.1.1?Sample Rate (samples per second)
采樣頻率:采樣率是指數據每秒的樣本數量。通常,它指的是我們采樣數據的速度,但對于模擬數據,它指的是我們生成樣本數據的速度。
4.3.1.2?Sample Number
樣本編號,這是絕對樣編號,從樣本0開始。當采樣數據收集開始時,收集的第一個樣本是樣本號0。下一個采集的樣本是樣本1,以此類推。這在模擬數據中也是如此。提供的第一個樣本是樣本編號0,以此類推。
4.3.1.3 U32 GenerateSimulationData( U64 largest_sample_requested, U32 sample_rate, SimulationChannelDescriptor** simulation_channel )
這個API 主要由Logic.exe 調用,Logic.exe 通過反復調用此函數以請求更多的模擬波形數據。因此,用戶需要在重寫這個函數,在函數里面生成自定義分析器Analyzer 需要的樣本數據,
值得注意的是,這個函數雖然由Logic.exe 調用, 但是也只有在調試模式時用得到。 意思是,如果對自己WorkThread 寫的自定義分析器代碼有信心,不需要模擬波形調試,這個方法可以空著。
在新版的Logic.exe 是不允許進行附件調試的,也就是,這個函數一般用戶 Saleae SDK 1.1.14 和 Logic 1.1.18 一起調試時用到。
4.4 SimulationChannelDescriptor
模擬通道描述符,這類使用于定義訪問單個通道的模擬樣本數據,以及它的波形。
通道的初始狀態(一般為BIT_LOW,或BIT_HIGH)。
通道的初始位狀態永遠不會改變,因此,一個特定樣本數的狀態(高或低)可以通過知道它切換到該點的次數(偶數或奇數)來確定。
換句話說:在一開始,指定了模擬通道的初始狀態(BIT_LOW或BIT_HIGH),這是樣本號(Sample Numer)為0的狀態。接著,可以繼續移動和向前(Advance)一些樣本。
例如,移動或則前進20個樣本, 即:Advance(20) 然后,我們切換通道(低變高,高變低, 如:Transition 或 TransitionIfNeeded) ,然后我們繼續向前(Advance)一些。
這次可能有100個樣本或則N個樣本,然后我們再次切換狀態,然后我們再次前進,然后我們再次切換,等等。
值得注意的是:
a. 前進(Advance) 多少個樣本,是根據用戶使用協議決定的,而不是固定需要多少個樣本。?
b. 切換狀態是指BitState 上面也講述過, BIT_LOW 表示下降沿, BIT_HIGH 表示上升沿。
4.4.1 SimulationChannelDescriptor API 說明
4.4.1.1 void Advance( U32 num_samples_to_advance );
這個函數主要在模擬波形中前進的方式,即在樣本流中移動,這函數會改變樣本流的位置。在SimulationChannelDescriptor對象內部,對象會跟蹤并記錄其樣本號Sample Number是什么, 即 Sample Number 會跟著改變。
樣本編號固定從0開始。
例如:
Advance(10);
Advance(20);
Advance(30);
則 Sample Number 從 0 前進或移動到 10 + 20 + 30 = 60, 即: 上面成功調用3次函數后,當前樣本編號為 60.
4.4.1.2 void Transition();
這函數切換通道的BitState, 將通道當前的BitState, 由BIT_LOW變成了BIT_HIGH,BIT_HIGH變成了BIT_LOW。
切換后,當前為新的BitState (BIT_LOW或BIT_HIGH),之后的所有Sample Number BitState 也將成為新的BitState,直到我們再次調用Transition()切換。
4.4.1.3 void TransitionIfNeeded( BitState bit_state );
一般的用戶不會主動跟蹤當前的BitState,但是, 它在每次調用Transition 時都會切換,
使用Transition,每次需要調用GetCurrentBitState()檢查當前的BitState,并且只有在當前的BitState與我們需要的BitState不同時才會進行Transition。
換句話說,“如果改變這個bit_state,我們還沒有”。
因此,官方提供了,TransitionIfNeeded 這個函數是不需要用戶知道或跟蹤當前Sample Number 的BitState 是什么,只有當前BitState 與 需要切換的BitState 不同
才會切換,如果一樣則保持。
4.4.1.4 BitState GetCurrentBitState();
這個函數允許直接詢問當前Sample Number的BitState是什么.
4.4.1.5 U64 GetCurrentSampleNumber();
這個函數允許您詢問當前的樣本編號Sample Number是什么.
4.5SimpleSerialAnalyzerResults.cpp 和 SimpleSerialAnalyzerResults.h
這個類主要是用于當自定義分析器Analyzer, 根據協議成功解析完通道的樣本數據后,如何在Logic.exe 中顯示解析后的樣本數據。
4.5.1 SimpleSerialAnalyzerResults API 說明
4.5.1.1 void GenerateBubbleText( U64 frame_index, Channel& channel,
DisplayBase display_base )
這個函數主要用于生成泡泡文本,將解碼后的數據文本放入氣泡中顯示的Logic屏幕上。
氣泡可以顯示不同長度的字符串,這取決于有多少可用的空間。
最簡單的可能簡單地表示內容的類型(例如數據的D”),較長的可能表示完整的數字(“0xFF01”)
需要注意的是,在添加任何字符串結果之前,始終調用ClearResultStrings() 清除上一次的顯示。
連接多個字符串,多次調用AddResultString() 即可。
4.5.1.2 void GenerateExportFile( const char* file, DisplayBase display_base, U32 export_type_user_id )
這個函數主要用于,當用戶試圖將分析器結果導出到文件中時,將調用此函數。
4.5.1.3 void SerialAnalyzerResults::GenerateFrameTabularText( U64 frame_index, DisplayBase display_base )
這個函數用于生成Logic.exe 框架表格文本, 添加文本,調用AddTabularText(),清除文本,調用 ClearTabularText().
如,解析后數據在1.2x 和 2.x 版本數據
上面講述了各個API 使用,應該足夠使用,更多可以參考官方提供的說明文檔,
關于調試,需要注意的是,
1. Logic 1.1.18 使用使用32位分析器, Logic 1.2 以上版本,根據安裝時的系統不同,需要的插件也不同,即x64 只能使用 64位版本分析器,x86 使用32位版本分析器。
同理,Logic 2.x 版本也是。
2. 無論那個 Logic.exe 都需要在指定分析器插件目錄后,再重啟軟件才能加載插件。
3. 在使用Logic 1.1.18 需要設置加載自定義分析器插件時,在某些系統可能找不到設置按鈕。因為開啟玻璃特效,所以被隱藏了。在win10 就是被隱藏掉。
?設置按鈕位于右上角
可以取消玻璃設置效果,如下圖
?終于寫完了。。。。。。。。。。。。。。。
/**
?* ┏┓ ┏┓+ +
?* ┏┛┻━━━┛┻┓ + +
?* ┃ ┃
?* ┃ ━ ┃ ++ + + +
?* ?████━████ ┃+
?* ┃ ┃ +
?* ┃ ┻ ┃
?* ┃ ┃ + +
?* ┗━┓ ┏━┛
?* ┃ ┃
?* ┃ ┃ + + + +
?* ┃ ┃ Code is far away from bug with the animal protecting
?* ┃ ┃ + 神獸保佑,代碼無bug
?* ┃ ┃
?* ┃ ┃ +
?* ┃ ? ┗━━━┓ + +
?* ┃ ┣┓
?* ┃ ┏┛
?* ┗┓┓┏━┳┓┏┛ + + + +
?* ┃┫┫ ┃┫┫
?* ┗┻┛ ┗┻┛+ + + +
?*
?* @author chenxi
?* @date 2021-11-29 22:05:41
?*/
總結
- 上一篇: 【opencv-ANNs】简单自动驾驶树
- 下一篇: 粗糙集理论,知识,知识库,知识表达系统