1. 程式人生 > >由FS_Seek()引數錯誤引發的有關定址範圍的思考

由FS_Seek()引數錯誤引發的有關定址範圍的思考

平臺:MT2503A

待實現功能:Fota

現象描述:

通過網路(wifi/lan)接收fota的分包並存儲進檔案系統,接收完畢進入bootloader升級後總是不能正常升級,將收到記錄的Fota檔案通過工具讀出並和原始檔案做對比發現許多地方不相同,開始懷疑是接收是出錯,利用debug打印出每一包的校驗資訊發現並沒有出錯,繼續向上檢視處理接收fota封包的函式(拆包後,儲存前),在儲存前做二次校驗,發現也沒有錯誤。由此可以斷定錯誤應該出在儲存過程中。

處理需要寫入的資料步驟:

1. fs_seek()

2. fs_write()

3.fs_fflush()

先將程式碼貼上,大家試試看能不能找到錯誤的地方:

/* MT2503 SDK中自帶函式 */
int FS_Seek(FS_HANDLE FileHandle, int Offset, int Whence)
{
    if (Whence != FS_FILE_BEGIN &&
        Whence != FS_FILE_CURRENT &&
        Whence != FS_FILE_END)
    {
        return FS_PARAM_ERROR;
    }
    
    return fs_bl_seek(FileHandle, Offset, Whence);
}

/* 同事重新封裝一次的程式碼 */
void fota_file_seek(FS_HANDLE handle, hal_uint16 position) 
{
    FS_Seek(handle, position, FS_FILE_BEGIN);
}

void fota_file_writr(FS_HANDLE handle, kal_char *data, kal_uint16 total_len)
{
........

    write_ret = FS_Write(handle, (kal_uint8 *)(data + len), total_len - len, &size);
    FS_Commit(handle);

........
}


void fota_handle_firmware_package(kal_char *firm_data, kal_uint16 package_id, kal_uint16 package_len) 
{
    ........ 
	fota_file_seek(fota_context.kedas_firmware, (package_id-1)*FIRM_WARE_PACKAGE_SIZE);
	fota_file_write(fota_context.kedas_firmware, firm_data, package_len);
    ........
}
    

第一次檢查程式碼時還沒有發現錯誤,所以又去檢視一次檔案比對,發現錯誤總在檔案64kB的地方之後開始出現,隱約覺得是不是MT2503的SDK限制寫入檔案大小,遂打電話給供應商的FAE詢問,檔案系統有沒有限制大小,FAE回答絕不可能出現只能寫了64KB。一般來說只要不超過剩餘flash大小的上限是都可以寫入的。

所以我再次去檢視程式碼,發現了一個很費解的錯誤,同事將fs_seek()函式重新打包了一下,SDK中的fs_seek()需要傳入三個引數分別是:fs_handle(相當於檔案描述符),int型的offset(偏移位置,請注意是int型,2^31定址範圍),int型的whence(表明從頭,從尾查詢),同事二次封裝的fota_file_seek(FS_HANDLE handle, hal_uint16 position) 函式只有兩個引數,相比他是想省一個函式並且讓只在fota的功能中使用,但是注意這個position引數是 hal_uint16 型別

(2^16定址範圍,剛好64KB啊,o(╥﹏╥)o,原來是你啊),恍然大悟。。。,將引數修改為int,再次測試一遍升級流程,接收檔案沒有錯誤,寫入正確,升級成功。

最後,總結一下關於這次debug得出的程式設計經驗:

1. 如果SDK中沒有必要二次封裝的函式就不要封裝了(就是這種你只能省下一個引數,沒有特殊的資料處理),老老實實呼叫就好,

2. 對於系統函式,該傳什麼型別引數就傳什麼。

再留一點地方,有時間把定址範圍推到一下。嘿嘿嘿。