# VU Table 對齊步驟指南(修正版) ## 一、對齊原則 **重要**:**FW 版本是正確的基準版本**,Regression Test 版本需要對齊到 FW 版本。 | 版本 | 狀態 | 用途 | |------|------|------| | **FW 版本** | ✅ **基準版本** | 實際 Firmware 使用,使用 Designated Initializers | | **Regression Test 版本** | ⚠️ **需要對齊** | 測試環境使用,使用傳統語法,必須對齊 FW 版本 | ## 二、檔案位置 | 項目 | 檔案位置 | 行數範圍 | 條件編譯 | |------|---------|---------|---------| | **ENUM_VU_STATE** | `Source/UFS/ISP/Vcmd/ISP_UFS_Vcmd.h` | 40-296 | - | | **FW VU_TABLE** | `Source/UFS/ISP/Vcmd/ISP_UFS_Vcmd_Para.c` | 20-1053 | `#ifndef SMI_REGRESSION_TEST` | | **Regression VU_TABLE** | `Source/UFS/ISP/Vcmd/ISP_UFS_Vcmd_Para.c` | 1054-1637 | `#ifdef SMI_REGRESSION_TEST` | | **FW VUHandler** | `Source/UFS/ISP/Vcmd/ISP_UFS_Vcmd_Rsp.c` | 182-389 | `#ifndef SMI_REGRESSION_TEST` | | **Regression VUHandler** | `Source/UFS/ISP/Vcmd/ISP_UFS_Vcmd_Rsp.c` | 390-693 | `#ifdef SMI_REGRESSION_TEST` | ## 三、對齊步驟 ### 步驟 1:確認 FW 版本的 VU_TABLE(基準) **目標**:確認 FW 版本中所有已定義的狀態 **操作**: 1. 打開 `Source/UFS/ISP/Vcmd/ISP_UFS_Vcmd_Para.c` 2. 找到 `#ifndef SMI_REGRESSION_TEST` 區塊 (Line 19-1053) 3. **列出所有已初始化的狀態**,例如: ```c [VU_STATE_STRSMI_ENTER] = { ... } [VU_STATE_STRDVT1_ENTER] = { ... } [VU_STATE_GET_BADBLOCK_CNT_IND] = { ... } ``` **重點**: - ✅ FW 版本使用 Designated Initializers,可以跳過不需要的狀態 - ✅ 記錄每個狀態的完整設定值 - ✅ 注意條件編譯(`#ifdef`)的狀態 **範例**: ```c #ifndef SMI_REGRESSION_TEST const ST_VU_CHK VU_TABLE[VU_STATE_END] = { [VU_STATE_STRSMI_ENTER] = { .u32CMD_Sig = VCMD_ARG_SMIPAR, .u08Opcode = UPIU_CMD_WRITE_BUFFER, .Next_State = VU_STATE_CHK_ENTER, .u32Len = 0x00, .u32Mode_SP_BT = ALL_MODE_SP }, // ... 其他狀態 }; #endif ``` ### 步驟 2:確認 ENUM_VU_STATE 的順序 **目標**:確認每個狀態在 enum 中的索引值 **操作**: 1. 打開 `Source/UFS/ISP/Vcmd/ISP_UFS_Vcmd.h` 2. 找到 `typedef enum { ... } ENUM_VU_STATE;` (Line 40-296) 3. **建立索引對照表**: ``` VU_STATE_START = 0 VU_STATE_STRDVT1_ENTER = 1 VU_STATE_STRDVT2_ENTER = 2 ... VU_STATE_GET_BADBLOCK_CNT_IND = 84 (假設) VU_STATE_GET_BADBLOCK_CNT_SIG = 225 (假設) ... VU_STATE_END = N // 最後一個狀態的索引 + 1 ``` **重點**: - ✅ 確認 `VU_STATE_END` 的值 - ✅ 確認 `VU_STATE_CHK_ENTER` 不在陣列範圍內 - ✅ 注意條件編譯的狀態 ### 步驟 3:對齊 Regression Test 版本的 VU_TABLE **目標**:讓 Regression Test 版本對齊 FW 版本 **操作流程**: #### 3.1 建立對照表 **從 FW 版本提取狀態設定**: ```c // FW 版本 (基準) [VU_STATE_GET_BADBLOCK_CNT_IND] = { .u32CMD_Sig = VCMD_GET_BADBLOCK_CNT, .u08Opcode = UPIU_CMD_WRITE_BUFFER, .Next_State = VU_STATE_GET_BADBLOCK_CNT_SIG, .u32Len = 0x0, .u32Mode_SP_BT = DVT1_MODE_SP|SMI_MODE_SP } ``` **轉換為 Regression Test 格式**: ```c // Regression Test 版本 (需要對齊) // 假設 VU_STATE_GET_BADBLOCK_CNT_IND = 84 // 結構體成員順序:{ u32CMD_Sig, u32Len, u32Mode_SP_BT, Next_State, u08Opcode } { VCMD_GET_BADBLOCK_CNT, 0x0, DVT1_MODE_SP|SMI_MODE_SP, VU_STATE_GET_BADBLOCK_CNT_SIG, UPIU_CMD_WRITE_BUFFER }, // [84] VU_STATE_GET_BADBLOCK_CNT_IND ``` #### 3.2 按照 ENUM 順序填入 **關鍵規則**: - ⚠️ **必須按照 ENUM_VU_STATE 的順序**(從 0 到 VU_STATE_END-1) - ⚠️ **不能跳過任何元素**(即使 FW 版本沒有初始化,也要填預設值) - ⚠️ **註解必須標註狀態名稱和索引** **對齊方法**: 1. **從索引 0 開始,逐一對齊**: ```c #ifdef SMI_REGRESSION_TEST const ST_VU_CHK VU_TABLE[VU_STATE_END] = { // [0] VU_STATE_START // 檢查 FW 版本是否有定義 // 如果 FW 版本沒有定義,使用預設值 { 0x00, 0x00, 0x00, VU_STATE_CHK_ENTER, 0x00 }, // VU_STATE_START, // [1] VU_STATE_STRDVT1_ENTER // 從 FW 版本複製設定值 { VCMD_ARG_DVT1PAR, 0x00, ALL_MODE_SP, VU_STATE_CHK_ENTER, UPIU_CMD_WRITE_BUFFER }, // VU_STATE_STRDVT1_ENTER, // ... 繼續對齊所有狀態 }; #endif ``` 2. **處理 FW 版本中未定義的狀態**: ```c // 如果 FW 版本中某個狀態沒有初始化(跳過),Regression Test 版本要填預設值 { 0x00, 0x00, 0x00, VU_STATE_START, 0x00 }, // VU_STATE_XXX (FW 版本未定義) ``` 3. **處理條件編譯**: ```c // FW 版本 #ifdef VCMD_GET_BADBLOCK_CNT [VU_STATE_GET_BADBLOCK_CNT_IND] = { ... }, #endif // Regression Test 版本(必須保留位置) #ifdef VCMD_GET_BADBLOCK_CNT { VCMD_GET_BADBLOCK_CNT, 0x0, DVT1_MODE_SP|SMI_MODE_SP, VU_STATE_GET_BADBLOCK_CNT_SIG, UPIU_CMD_WRITE_BUFFER }, // [84] VU_STATE_GET_BADBLOCK_CNT_IND #else { 0x00, 0x00, 0x00, VU_STATE_START, 0x00 }, // [84] VU_STATE_GET_BADBLOCK_CNT_IND (未啟用) #endif ``` #### 3.3 結構體成員順序 **重要**:Regression Test 版本使用傳統語法,成員順序必須正確: ```c // ST_VU_CHK 結構定義 typedef struct { LWORD u32CMD_Sig; // 第 1 個成員 LWORD u32Len; // 第 2 個成員 LWORD u32Mode_SP_BT; // 第 3 個成員 ENUM_VU_STATE Next_State; // 第 4 個成員 BYTE u08Opcode; // 第 5 個成員 } ST_VU_CHK; // Regression Test 初始化順序 { u32CMD_Sig, u32Len, u32Mode_SP_BT, Next_State, u08Opcode } ``` **對照範例**: ```c // FW 版本 (Designated Initializers) [VU_STATE_GET_BADBLOCK_CNT_IND] = { .u32CMD_Sig = VCMD_GET_BADBLOCK_CNT, // 成員 1 .u32Len = 0x0, // 成員 2 .u32Mode_SP_BT = DVT1_MODE_SP|SMI_MODE_SP, // 成員 3 .Next_State = VU_STATE_GET_BADBLOCK_CNT_SIG, // 成員 4 .u08Opcode = UPIU_CMD_WRITE_BUFFER // 成員 5 } // Regression Test 版本 (傳統語法) { VCMD_GET_BADBLOCK_CNT, // 成員 1: u32CMD_Sig 0x0, // 成員 2: u32Len DVT1_MODE_SP|SMI_MODE_SP, // 成員 3: u32Mode_SP_BT VU_STATE_GET_BADBLOCK_CNT_SIG, // 成員 4: Next_State UPIU_CMD_WRITE_BUFFER }, // 成員 5: u08Opcode // [84] VU_STATE_GET_BADBLOCK_CNT_IND ``` ### 步驟 4:對齊 Regression Test 版本的 VUHandler **目標**:讓 Regression Test 版本的 VUHandler 對齊 FW 版本 **操作流程**: #### 4.1 從 FW 版本提取處理函數 ```c // FW 版本 (基準) #ifndef SMI_REGRESSION_TEST FuncVUHandle VUHandler[VU_STATE_END] = { [VU_STATE_GET_BADBLOCK_CNT_SIG] = ISP_UFS_VCmd_GeneralVU_Read, [VU_STATE_GETFWVERSION_SIG] = ISP_UFS_VCmd_GetFWVersion, // ... 其他狀態 }; #endif ``` #### 4.2 按照 ENUM 順序填入 Regression Test 版本 ```c // Regression Test 版本 (需要對齊) #ifdef SMI_REGRESSION_TEST FuncVUHandle VUHandler[VU_STATE_END] = { NULL, // [0] VU_STATE_START (FW 版本未定義) ISP_UFS_VCmd_Enter_DVT1, // [1] VU_STATE_STRDVT1_ENTER (從 FW 版本複製) ISP_UFS_VCmd_Enter_DVT2, // [2] VU_STATE_STRDVT2_ENTER (從 FW 版本複製) // ... NULL, // [84] VU_STATE_GET_BADBLOCK_CNT_IND (FW 版本未定義) // ... ISP_UFS_VCmd_GeneralVU_Read, // [225] VU_STATE_GET_BADBLOCK_CNT_SIG (從 FW 版本複製) // ... }; #endif ``` **重點**: - ✅ 如果 FW 版本有定義處理函數,複製到對應位置 - ✅ 如果 FW 版本沒有定義(跳過),填 `NULL` - ✅ 必須按照 ENUM 順序,不能跳過任何元素 ## 四、完整對齊範例 ### 範例:對齊 VU_STATE_GET_BADBLOCK_CNT_IND 和 VU_STATE_GET_BADBLOCK_CNT_SIG #### 1. FW 版本(基準) **VU_TABLE**: ```c #ifndef SMI_REGRESSION_TEST const ST_VU_CHK VU_TABLE[VU_STATE_END] = { // ... [VU_STATE_GET_BADBLOCK_CNT_IND] = { // 假設 enum 值 = 84 .u32CMD_Sig = VCMD_GET_BADBLOCK_CNT, .u08Opcode = UPIU_CMD_WRITE_BUFFER, .Next_State = VU_STATE_GET_BADBLOCK_CNT_SIG, .u32Len = 0x0, .u32Mode_SP_BT = DVT1_MODE_SP|SMI_MODE_SP }, // ... [VU_STATE_GET_BADBLOCK_CNT_SIG] = { // 假設 enum 值 = 225 .u32CMD_Sig = VCMD_GET_BADBLOCK_CNT, .u08Opcode = UPIU_CMD_READ_BUFFER, .Next_State = VU_STATE_START, .u32Len = 0x1000, .u32Mode_SP_BT = ALL_MODE_SP }, // ... }; #endif ``` **VUHandler**: ```c #ifndef SMI_REGRESSION_TEST FuncVUHandle VUHandler[VU_STATE_END] = { // ... [VU_STATE_GET_BADBLOCK_CNT_SIG] = ISP_UFS_VCmd_GeneralVU_Read, // 索引 225 // ... (VU_STATE_GET_BADBLOCK_CNT_IND 沒有處理函數,跳過) }; #endif ``` #### 2. Regression Test 版本(對齊) **VU_TABLE**: ```c #ifdef SMI_REGRESSION_TEST const ST_VU_CHK VU_TABLE[VU_STATE_END] = { // ... 前面的 83 個元素 ... // [84] VU_STATE_GET_BADBLOCK_CNT_IND // 從 FW 版本複製:{ u32CMD_Sig, u32Len, u32Mode_SP_BT, Next_State, u08Opcode } { VCMD_GET_BADBLOCK_CNT, // u32CMD_Sig 0x0, // u32Len DVT1_MODE_SP|SMI_MODE_SP, // u32Mode_SP_BT VU_STATE_GET_BADBLOCK_CNT_SIG, // Next_State UPIU_CMD_WRITE_BUFFER }, // u08Opcode // VU_STATE_GET_BADBLOCK_CNT_IND // ... 中間的元素 ... // [225] VU_STATE_GET_BADBLOCK_CNT_SIG // 從 FW 版本複製 { VCMD_GET_BADBLOCK_CNT, // u32CMD_Sig 0x1000, // u32Len ALL_MODE_SP, // u32Mode_SP_BT VU_STATE_START, // Next_State UPIU_CMD_READ_BUFFER }, // u08Opcode // VU_STATE_GET_BADBLOCK_CNT_SIG // ... 後面的元素 ... }; #endif ``` **VUHandler**: ```c #ifdef SMI_REGRESSION_TEST FuncVUHandle VUHandler[VU_STATE_END] = { // ... 前面的元素 ... NULL, // [84] VU_STATE_GET_BADBLOCK_CNT_IND (FW 版本未定義處理函數) // ... 中間的元素 ... ISP_UFS_VCmd_GeneralVU_Read, // [225] VU_STATE_GET_BADBLOCK_CNT_SIG (從 FW 版本複製) // ... 後面的元素 ... }; #endif ``` ## 五、對齊檢查清單 ### 新增狀態時的對齊步驟 1. **在 FW 版本中添加狀態**: - [ ] 在 `ENUM_VU_STATE` 中添加新狀態 - [ ] 在 FW VU_TABLE 中添加狀態初始化(使用 Designated Initializers) - [ ] 在 FW VUHandler 中添加處理函數(如果需要) 2. **在 Regression Test 版本中對齊**: - [ ] 確認新狀態在 ENUM 中的索引位置 - [ ] 在 Regression Test VU_TABLE 的**對應索引位置**添加狀態(使用傳統語法) - [ ] 在 Regression Test VUHandler 的**對應索引位置**添加處理函數(或 NULL) - [ ] 確認註解標註正確的狀態名稱和索引 3. **驗證**: - [ ] 確認陣列大小 = `VU_STATE_END` - [ ] 確認 Regression Test 版本的元素數量正確 - [ ] 確認結構體成員順序正確 - [ ] 編譯測試(FW 和 Regression Test 版本) ### 修改狀態時的對齊步驟 1. **修改 FW 版本**: - [ ] 修改 FW VU_TABLE 中的狀態設定 - [ ] 修改 FW VUHandler 中的處理函數(如果需要) 2. **同步到 Regression Test 版本**: - [ ] 找到對應的索引位置 - [ ] 更新 Regression Test VU_TABLE 中對應位置的設定 - [ ] 更新 Regression Test VUHandler 中對應位置的處理函數 - [ ] 確認註解正確 ## 六、常見錯誤與解決方法 ### 錯誤 1:索引位置錯誤 **症狀**:Regression Test 版本中狀態對應錯誤 **原因**: - 沒有按照 ENUM 順序填入 - 索引計算錯誤 **解決方法**: 1. 確認狀態在 ENUM 中的索引值 2. 確認 Regression Test 版本中該索引位置的元素正確 3. 使用註解標註索引和狀態名稱 ### 錯誤 2:結構體成員順序錯誤 **症狀**:編譯通過但執行時行為錯誤 **原因**: - 傳統語法的成員順序與結構定義不一致 **解決方法**: ```c // 正確順序(對照結構定義) { u32CMD_Sig, u32Len, u32Mode_SP_BT, Next_State, u08Opcode } // 檢查方法:對照 FW 版本的 Designated Initializers ``` ### 錯誤 3:遺漏未定義的狀態 **症狀**:陣列大小不匹配 **原因**: - FW 版本跳過的狀態,Regression Test 版本沒有填預設值 **解決方法**: - 所有索引位置都要有元素(即使填 `{ 0x00, 0x00, 0x00, VU_STATE_START, 0x00 }`) ### 錯誤 4:條件編譯處理不一致 **症狀**:不同編譯條件下行為不一致 **原因**: - FW 和 Regression Test 版本的條件編譯分支不一致 **解決方法**: - 確保兩個版本的 `#ifdef` 條件一致 - Regression Test 版本必須保留位置(即使條件不滿足) ## 七、實用工具腳本 ### 提取 FW 版本狀態列表 ```bash # 提取 FW VU_TABLE 中所有定義的狀態 grep -E "\[VU_STATE_" Source/UFS/ISP/Vcmd/ISP_UFS_Vcmd_Para.c | \ grep -v "^#" | \ sed 's/.*\[\(VU_STATE_[^]]*\)\].*/\1/' | \ sort > fw_states.txt ``` ### 檢查 Regression Test 版本註解 ```bash # 檢查 Regression Test 版本的註解是否正確 grep -E "//.*VU_STATE_" Source/UFS/ISP/Vcmd/ISP_UFS_Vcmd_Para.c | \ grep -A 1 "#ifdef SMI_REGRESSION_TEST" | \ head -50 ``` ### 驗證陣列大小 ```c // 在程式碼中加入編譯時檢查 #ifdef SMI_REGRESSION_TEST // 確認陣列大小 static_assert(sizeof(VU_TABLE) / sizeof(VU_TABLE[0]) == VU_STATE_END, "Regression VU_TABLE size mismatch!"); static_assert(sizeof(VUHandler) / sizeof(VUHandler[0]) == VU_STATE_END, "Regression VUHandler size mismatch!"); #endif ``` ## 八、總結 **對齊原則**: 1. ✅ **FW 版本是基準**:所有修改先在 FW 版本進行 2. ✅ **Regression Test 版本對齊 FW**:按照 ENUM 順序,複製 FW 版本的設定 3. ✅ **不能跳過元素**:Regression Test 版本必須填滿所有索引位置 4. ✅ **註解必須正確**:標註狀態名稱和索引,方便維護 5. ✅ **結構體順序**:傳統語法必須按照結構定義的順序 **關鍵檢查點**: - ✅ 陣列大小 = `VU_STATE_END` - ✅ 索引對應 ENUM 值 - ✅ 結構體成員順序正確 - ✅ 條件編譯分支一致 - ✅ 註解標註正確