Skip to Content
Plugin 開發參考文件API 參考:Job 與 Slave 宣告

API 參考:NxJobRequest 與 NxSlaveDecl

本頁內容與 PDK 內的 docs\NEXUS_TUI_PLUGIN_API_REFERENCE.md 相同(依章節分頁,連結已改成站內連結)。

3.1 NxJobRequest

NxJobRequest::size_of_struct

型別:NxDword

意義:本結構的位元組大小,供 Core 判定呼叫端這次提供到哪個欄位為止——SubmitJob()/ExecSync() 共用同一份降級判定。

合法值/哨兵:填 (NxDword)sizeof(NxJobRequest)。兩個入口皆要求至少涵蓋到 user_data(ABI 2 既有欄位的尾端);小於這個下限一律 ERR_INVALID_PARAM。ABI 3.0 起結尾追加的 rx_len/bus_name 未涵蓋在內時(較舊 ABI 的 Plugin)視為未提供(等同預設值),不是錯誤,見 NxJobRequest::rx_len、NxJobRequest::bus_name。

何時填:每次建構 NxJobRequest 時,memset 之後立即填。

NxJobRequest::op

型別:NxByte

意義:操作種類,決定 Core 接下來實際對硬體做什麼、以及本結構其餘欄位中哪些會被讀取。

合法值/哨兵:

值常數用到的欄位忽略的欄位
0NX_JOB_READoffset、lengthdata、and_mask、or_mask、rx_len
1NX_JOB_WRITEoffset、length、dataand_mask、or_mask、rx_len
2NX_JOB_RMWoffset、and_mask、or_mask(length 必須為 1,見 NxJobRequest::length)data、rx_len
3NX_JOB_BANK_SWITCHbank(length 恆為 0)offset、data、and_mask、or_mask、rx_len
4NX_JOB_XFERdata(傳輸前綴,length 為其長度,可為 0 表示 address-only 探測)、rx_len(讀回長度)offset(忽略——前綴資料本身就是位移;本 op 不進 RegModel)
5NX_JOB_VENDOR(ABI 4.1)vendor_op(op 名稱)、data/length(已編碼的 payload)其餘全部;只有 ExecSync() 支援,SubmitJob() 回 ERR_NOT_SUPPORTED,見 NxJobRequest::vendor_op

不是以上六者之一:ERR_INVALID_PARAM(SubmitJob()/ExecSync() 皆把這個檢查排在其餘一切解析之前)。NX_JOB_XFER 是否真正支援由連線的後端決定,Plugin 無法事先查詢,只能以實際呼叫後的回傳碼判定——後端不支援時回 ERR_NOT_SUPPORTED,具備能力時會先確保 Bank 正確再執行真正的傳輸,成功回 ERR_OK,失敗回匯流排層級的錯誤碼。

何時填:每次呼叫 SubmitJob()/ExecSync() 之前。

NxJobRequest::priority

型別:NxByte

意義:非同步 Job 的佇列優先級,決定它排進高優先級佇列還是低優先級佇列。

合法值/哨兵:NX_JOB_PRI_HIGH(0,使用者主動操作,永遠先於低優先級執行)/NX_JOB_PRI_LOW(1,背景輪詢;poll off,或該後端執行期離線降級狀態下由背景來源送出者一律回 ERR_POLL_DISABLED)。兩者之外一律 ERR_INVALID_PARAM。ExecSync() 完全忽略本欄位——同步執行不經佇列,沒有優先級可言;只有 SubmitJob() 依此決定入哪一條佇列。

何時填:使用 SubmitJob() 時必填;使用 ExecSync() 時可留任意值(含 memset 後的 0),不影響行為。

NxJobRequest::slave_addr

型別:NxByte

意義:7-bit I2C slave 位址;0 是哨兵,代表「沿用本掛載目前綁定的位址」,不是位址本身。

合法值/哨兵:0x00~0x7F 是正常值域;0 =沿用本掛載目前的位址;非 0 時該值具權威,且不侷限於本掛載自己宣告的位址——Core 在同 Tab、同後端上尋找綁著這個位址的掛載並對它存取,找到即對它存取,找不到則落回表外(flat 8-bit、不進 RegModel,回 ERR_OK 而非拒絕)。0x00 在 I2C 上是保留的 general-call 位址,永遠不會是一顆裝置的位址,故拿它當哨兵不損失任何合法值域。> 0x7F 一律視為 8-bit write-address 並自動換算成 7-bit(>> 1,不分奇偶:0x90/0x91 都換成 0x48,最低位是 R/W 位)——ExecSync 與 NxHostApi::SubmitJob 兩個入口逐位元組一致,都在解析目標掛載之前換算,故換算後的值同時決定了找不找得到掛載、也決定了實際打上匯流排的位址。首次換算會就該掛載記一筆 NX_LOG_WARN(訊息含原值與換算後的值),同一個掛載之後的換算不再重複記錄。韌體常見的 8-bit(write-address,含 R/W 位元)數值即使沒有自己先右移一位,也會被換算到正確的裝置——但仍建議填 7-bit:自動換算是安全網,不是省事的理由,且 0xFF/未初始化值也會被換成 0x7F 並真的去存取。

何時填:需要覆寫掛載目前位址、或存取同一後端上另一顆已掛載裝置時填非 0;其餘情況(含最常見的「就是我自己這顆」)留 0(memset 後的預設值)。不要填自己 slaves[] 裡宣告的位址——宣告位址只在掛載當下、且該槽尚未被使用者設過位址時才會寫進掛載設定,此後使用者隨時可以改掉它;這樣填會在使用者改過掛載位址之後讀錯裝置,且不報錯。

NxJobRequest::bank

型別:NxByte

意義:目標 Bank;0 與非 0 語意不對稱,不是一般「填 0 表示未設定」的慣例。

合法值/哨兵:0 =沿用本掛載記得的目前頁(可以合法是 0,不是「不帶 bank」);非 0 =單次覆寫,不更動本掛載記得的頁。沒有 bank register 的掛載,或表外位址(見 NxJobRequest::slave_addr)帶非 0 的 bank:一律 ERR_INVALID_PARAM。

何時填:需要單次覆寫目前頁時填非 0;沿用目前頁(最常見)留 0。

NxJobRequest::offset

型別:NxWord

意義:暫存器位移。

合法值/哨兵:0x0000~0xFFFF。本掛載宣告 16-bit 定址、但連線後端未宣告對應能力時,兩個入口最終都回 ERR_NOT_SUPPORTED,但送達的時機不同:ExecSync() 是同步執行,直接以這次呼叫的回傳值回報;SubmitJob() 的這項能力查核發生在 Job 真正被執行的當下(即該筆 Job 完成時),不是入列當下——SubmitJob() 自己的回傳值只代表「有沒有成功入列」,ERR_NOT_SUPPORTED 要靠 on_complete 的 rc 參數(或 Log)才看得到。8-bit 定址(含 IC:none 與表外存取的預設寬度)下 > 0xFF 時,兩個入口行為一致:SubmitJob() 在入列前就明確拒絕並直接回傳 ERR_INVALID_PARAM;ExecSync() 對表外(不屬於任何掛載)的位址與已掛載的 8-bit 裝置一律做同一項拒絕,回 ERR_INVALID_PARAM,不會把位移截斷後送去硬體。8-bit 裝置上沒有無損的換算方式可猜(那顆 IC 根本沒有那個暫存器),故這裡是拒絕,不像 NxJobRequest::slave_addr 的 > 0x7F 那樣自動換算。NX_JOB_XFER 忽略本欄位(前綴資料本身就是位移,見 NxJobRequest::op)。

何時填:NX_JOB_READ/WRITE/RMW 必填;NX_JOB_BANK_SWITCH/NX_JOB_XFER 不讀取,可留 0。

NxJobRequest::length

型別:NxWord

意義:讀取的位元組數,或 data 中待寫入/傳輸前綴的位元組數。

合法值/哨兵:依 op 各自不同的上限,四條規則互不相通:

  • NX_JOB_READ/NX_JOB_WRITE:1~256(一個 bank)。0 或超過 256 時,兩個入口都直接拒絕並回 ERR_INVALID_PARAM:ExecSync() 以這次呼叫的回傳值回報,SubmitJob() 在入列當下就以自己的回傳值回報(不入列、不會呼叫 on_complete)。這項拒絕不碰硬體,也不計入匯流排的連續失敗次數——填錯長度不會讓匯流排被判離線。NX_JOB_MAX_PAYLOAD(512)只適用 NX_JOB_XFER,不是本 op 的上限;需要更長的連續存取請分段送出,或改用 NX_JOB_XFER。
  • NX_JOB_RMW:必須恰為 1,不是「Core 覆寫成 1」。兩個入口都明確檢查 length != 1 並回 ERR_INVALID_PARAM,不符時整筆請求被拒絕,不會被靜默改成 1 後繼續執行。
  • NX_JOB_BANK_SWITCH:本欄位對本 op 不生效,Plugin 填什麼值都不影響行為——SubmitJob() 路徑最終記錄的 Job 長度固定為 0;ExecSync() 路徑完全不檢查、也不使用本欄位。
  • NX_JOB_XFER:0~NX_JOB_MAX_PAYLOAD(512);0 合法,代表 address-only cycle(用於探測位址是否存在)。

何時填:NX_JOB_READ/WRITE/XFER 必填;NX_JOB_RMW 必須明確填 1;NX_JOB_BANK_SWITCH 可留 0(本欄位被忽略)。

NxJobRequest::data

型別:const NxByte *

意義:NX_JOB_WRITE 的寫入來源資料,或 NX_JOB_XFER 的傳輸前綴。

合法值/哨兵:NX_JOB_WRITE:不得為 NULL,否則 ERR_INVALID_PARAM;由 Core 在入列(SubmitJob())或執行當下(ExecSync())複製前 length 個位元組,函式返回後呼叫端即可重複使用此緩衝區,不需要保留到非同步完成為止。NX_JOB_XFER 且 length > 0:同 NX_JOB_WRITE 的 NULL 檢查與複製時機。NX_JOB_READ:Core 不讀取本欄位,建議填 NULL。NX_JOB_RMW/NX_JOB_BANK_SWITCH:Core 不讀取本欄位。

何時填:僅 NX_JOB_WRITE,以及帶前綴的 NX_JOB_XFER(length > 0)需要。

NxJobRequest::and_mask

型別:NxByte

意義:NX_JOB_RMW 的 AND 遮罩:new = (old & and_mask) | or_mask,封裝在同一個 Job 內以保證原子性。

合法值/哨兵:任意位元組;NX_JOB_RMW 以外的 op 一律忽略本欄位。

何時填:僅 NX_JOB_RMW 需要。

NxJobRequest::or_mask

型別:NxByte

意義:NX_JOB_RMW 的 OR 遮罩,見 NxJobRequest::and_mask。

合法值/哨兵:任意位元組;NX_JOB_RMW 以外的 op 一律忽略本欄位。

何時填:僅 NX_JOB_RMW 需要。

NxJobRequest::on_complete

型別:NxJobCompleteFn(函式指標,簽章 void (NX_CALL *)(NxPluginCtx ctx, NxLong rc, const NxByte *data, NxWord len, void *user_data))

意義:非同步 Job 完成時的回呼,SubmitJob() 專用。在該 Job 所屬後端的 I2C Worker Thread 上呼叫(sdk/nexus_plugin_api.h 對 NxJobCompleteFn 的 @warning;並非全域唯一一條,同一掛載的 callback 仍永不與自己並行,見 PLUGIN_GUIDE 第 4 章)。禁止在回呼內呼叫任何 UI 渲染函式,需要重繪請呼叫 NotifyUiRefresh()。data 僅在本次呼叫期間有效,需要保留請自行複製。SubmitJob() 入列失敗時本回呼不會被呼叫一次。ExecSync() 完全忽略本欄位(同步呼叫本身就是「完成」,沒有回呼的必要)。

合法值/哨兵:不需要完成通知時填 NULL。

何時填:使用 SubmitJob() 且需要在 Job 完成時收到通知時填;否則留 NULL。

NxJobRequest::user_data

型別:void *

意義:原樣回傳給 on_complete 的使用者資料指標;Core 不解讀、不釋放、不複製其指向內容。ExecSync() 忽略本欄位。

合法值/哨兵:任意值,含 NULL。

何時填:需要在 on_complete 內辨識這是哪一次呼叫、或攜帶額外上下文時填;否則留 NULL。

NxJobRequest::rx_len

型別:NxWord

意義:NX_JOB_XFER 專用的讀回長度;其他 op 忽略。

合法值/哨兵:0~NX_JOB_MAX_PAYLOAD(512);超過上限一律 ERR_INVALID_PARAM(拒絕,不截斷——截斷會回 ERR_OK 加上一段比要求短的資料而零診斷)。本欄位需要 size_of_struct 涵蓋到才有效;較舊呼叫端(涵蓋不到)視為未提供,等同 0。

何時填:僅 NX_JOB_XFER 需要讀回資料時填;length == 0 的 address-only 探測可留 0。

NxJobRequest::bus_name

型別:char [NX_BACKEND_NAME_MAX](16)

意義:目標後端的名稱;空字串(bus_name[0] == '\0')=本掛載目前綁定的後端(預設)。

合法值/哨兵:空字串,或合法的後端名稱(NUL 結尾字串,比對方式與後端解析逐字相同);陣列內容未以 '\0' 結尾者為非法輸入,Core 不會替呼叫端補結尾。非空但找不到這個名稱:一律 ERR_HW_OFFLINE(名稱先解析,不會被誤報成 ERR_WRONG_THREAD)。ExecSync() 非空時要求呼叫端本身就在該名稱對應的 I2C Worker Thread 上,否則 ERR_WRONG_THREAD;SubmitJob() 非空時改把 Job 路由到該名稱對應匯流排自己的 Worker,不限呼叫執行緒。本欄位同樣需要 size_of_struct 涵蓋到才有效。

何時填:需要明確指定跨後端存取時填;memset 後的空字串已是最常見的「沿用本掛載後端」,memset(&req, 0, sizeof(req)) 因此同時是 slave_addr/bank/bus_name 三者「什麼都不覆寫」的慣用寫法。

NxJobRequest::reserved

型別:reserved0:NxWord(緊接 or_mask 之後);reserved1:NxByte [6](結構結尾)。

意義:對齊保留,供日後在結尾追加欄位使用。reserved1 存在的理由就是被縮小:日後結尾追加欄位時必須同步縮小 reserved1,使 rx_len/bus_name/reserved1 這個區塊維持 8 的倍數(見 sdk/nexus_plugin_api.h 對 reserved1 的 @note 不變式),否則編譯器補回的填補位元組會被算進 size_of_struct 卻不屬於任何欄位。

合法值/哨兵:一律填 0(memset 整個結構即可)。

何時填:宣告或建構時;Core 不讀取這些欄位的內容。

NxJobRequest::vendor_op

型別:const char *(ABI 4.1 結尾追加;接在 reserved1 之後,前面的 rx_len/bus_name/reserved1 區塊維持 8 的倍數,所以兩種位元寬度下都沒有填補位元組)

意義:NX_JOB_VENDOR 專用的 vendor op 名稱(NUL 結尾,區分大小寫,長度不超過 24 個位元組);其他 op 忽略。名稱對應 Dongle 自述的 op 目錄(Core 啟動連線時取回並快取);data/length 是已依目錄編碼的 payload,結果以零補滿 out 整段(ExecSync() 不回報實際長度)。

合法值/哨兵:目錄裡存在的 op 名稱。NULL 或空字串、超長名稱、payload 長度超出目錄宣告的範圍:ERR_INVALID_PARAM;名稱不在目錄裡:ERR_NOT_SUPPORTED;out_cap 小於目錄宣告的最長結果:ERR_BUFFER_TOO_SMALL(執行前就拒絕,不會先做了才發現放不下)。本欄位需要 size_of_struct 涵蓋到才有效;較舊呼叫端(4.0 大小的結構,涵蓋不到)送 NX_JOB_VENDOR 一律 ERR_INVALID_PARAM,因為無從定址。

何時填:呼叫 NxHostApi::ExecSync 執行 vendor op 時;SubmitJob() 不支援此 op(回 ERR_NOT_SUPPORTED)。呼叫前以 NX_ABI_HAS_FIELD(host->size_of_struct, NxHostApi, GpioPulse) 確認 Host 是 4.1 以上。

3.2 NxSlaveDecl

NxSlaveDecl::addr

型別:NxByte

意義:7-bit slave 位址;slaves[0] 是面板預設顯示對象(相當於舊版單一 default_addr 欄位的角色),slaves[1] 起是同一顆 IC 對外露出的其他位址。

合法值/哨兵:0x00~0x7F 是正常值域。0x00 是合法且有意義的宣告值,代表「本 Plugin 不綁定任何固定位址,請使用者自己設」——Core 刻意不在註冊時拒絕 addr == 0。GUI 對解析出來的掛載位址為 0x00 時會自動開啟位址設定對話框並閃爍警示外框;0x00 在 I2C 上是保留的 general-call 位址,永遠不會是一顆裝置的位址,本專案不支援 general-call 廣播,故此刻沒有歧義。宣告 > 0x7F(8051 韌體移植常見的 8-bit write-address,如 0x90)時,Core 在把這個值寫進掛載設定(mounts_cfg)之前先自動換算成 7-bit(連同一筆 NX_LOG_WARN),故 UI、config.ini、RegModel 看到的與實際線上交易恆是同一個 7-bit 值——但仍建議宣告時就直接填 7-bit,這個換算是安全網,不是省事的理由。

何時填:宣告 IcPlugin::slaves[] 靜態表時。宣告位址永遠不會被寫進掛載設定——寫入掛載位址的唯一入口是使用者的掛載指令,見 NxJobRequest::slave_addr。

NxSlaveDecl::addr_mode

型別:NxByte

意義:本位址的暫存器位移定址寬度。

合法值/哨兵:

值常數意義
0NX_ADDR_MODE_8BIT8-bit 暫存器位移定址
1NX_ADDR_MODE_16BIT16-bit 暫存器位移定址;連線後端未宣告對應能力時,相關存取一律回 ERR_NOT_SUPPORTED(見 NxJobRequest::offset)

何時填:宣告 IcPlugin::slaves[] 靜態表時,依實際 IC 規格填寫。

已知陷阱:slaves[0] 的 addr_mode 只在掛載槽目前沒有位址時才會被套用;使用者用 addr/mount 等指令先設定過該槽的位址之後,之後重新載入本 Plugin 不會覆寫既有的定址寬度——結果是一顆宣告 16-bit 的 IC 卻用 8-bit 定址存取,且不報錯(slaves[1]~slaves[15] 不受影響,每次都依宣告值套用)。

NxSlaveDecl::bank_mode

型別:NxByte

意義:本 IC 是否有 Bank/Page 概念。

合法值/哨兵:

值常數意義
0NX_BANK_MODE_NONE本 IC 沒有 Bank/Page 概念(flat 定址);收到非 0 的 NxJobRequest::bank 一律 ERR_INVALID_PARAM
1NX_BANK_MODE_REG以某個暫存器作為 bank-select register,位移見 NxSlaveDecl::bank_select_reg

何時填:同上。

NxSlaveDecl::bank_select_reg

型別:NxByte

意義:bank_mode == NX_BANK_MODE_REG 時的 bank 暫存器位移。

合法值/哨兵:0x00~0xFF——即使 addr_mode 為 16-bit(資料暫存器可到 0xFFFF),bank 暫存器位移上限仍是一個位元組,這是刻意的設計:十二份既有 IC 程式碼調查裡,具名的 bank 暫存器只落在 0x05/0x0F 兩個位移,唯一 16-bit 定址的那一份完全沒有 bank 概念。寫入範圍恰好等於這個位移的單一位元組時,該筆 NX_JOB_WRITE 由送出端攔截、轉換為等效的 Bank 切換執行;範圍涵蓋這個位移卻不恰好等於它(跨界或部分覆蓋)時,直接回 ERR_INVALID_PARAM,不嘗試拆分。

何時填:bank_mode == NX_BANK_MODE_REG 時填;NX_BANK_MODE_NONE 時填 0(Core 不讀取)。

NxSlaveDecl::bank_select_mask

型別:NxByte

意義:bank number 在 bank-select register 內所占的位元遮罩。

合法值/哨兵:0x00~0xFF;0 視同 0xFF(NX_BANK_MASK_NORMALIZE() 巨集的正規化規則:整個位元組即 bank number),向後相容「保留欄位一律填 0」的舊慣例——本欄位原是舊版 reserved0[3] 的第一個位元組。

何時填:bank_mode == NX_BANK_MODE_REG 且 bank number 只占暫存器部分位元時填實際遮罩;占滿整個位元組或不確定時填 0。

NxSlaveDecl::flags

型別:NxByte

意義:旗標位元集合。

合法值/哨兵:NX_SLAVE_F_OPTIONAL(0x01)——標記這是一個候選位址(例如同一顆 IC 依硬體接腳可能落在兩個位址之一);Core 目前只把這個旗標存進掛載狀態、不會讀取它來做任何判斷——逐位址「這個位址有沒有回應算不算數」完全是 Plugin 自己的事:ABI 的 probe() 只收一個 ctx、判定的是「這顆 Plugin 的硬體在不在」這一件事,逐 slave 的存在性判定要靠 Plugin 自己在 probe() 裡用 ExecSync 逐一確認。未定義位元須為 0。

何時填:宣告 IcPlugin::slaves[] 靜態表時。

NxSlaveDecl::label

型別:const char *

意義:顯示名稱,用於面板標題與掛載清單。

合法值/哨兵:靜態儲存期字串;NULL 時 Host 改以本位址的十六進位表示呈現。

何時填:宣告 IcPlugin::slaves[] 靜態表時;不需要自訂名稱可留 NULL。

NxSlaveDecl::reserved

型別:reserved0:NxByte [2](緊接 flags 之後,對齊用)。

意義:保留給日後結尾追加欄位使用。凍結對象(第一顆外部 Plugin 發佈後)只准結尾追加。

合法值/哨兵:一律填 0(memset 整個結構即可)。

何時填:宣告靜態表時;Core 不讀取這些欄位的內容。