# 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 值
- ✅ 結構體成員順序正確
- ✅ 條件編譯分支一致
- ✅ 註解標註正確