上次用字節(jié)方式寫文件成功了。但現(xiàn)在要記錄比較大的文件,要求速度,只好用突發(fā)方式。在一個地方卡住了,就是在用WR_HOST_DATA寫完64個字節(jié)后,返回操作失敗。研究很久不知道錯在哪里,寫信號的已經(jīng)降到只有100K左右了,絕對在數(shù)據(jù)手冊規(guī)定的時序范圍內(nèi)。U盤也換過,F(xiàn)AT32和FAT格式也都試過,都不行。 貼上實際采樣的時序,請高手分析一下。 請點擊圖片,顯示原始大小。
補(bǔ)充說明一下: 雖然操作失敗,但在U盤上也有一個文件,文件名是對的,但內(nèi)容不對。 原來是想存512個ASCII為“2F”(即"\"),結(jié)果里面總是只有一個字節(jié)的內(nèi)容,而且每次還不一樣,有時是"2",有時是".",有時是" "(空格)。 可以確認(rèn)寫完WR_HOST_DATA后,寫了一個0x40,然后64個0x2F(數(shù)過好幾遍)。
一般寫多少數(shù)據(jù)就會出現(xiàn)這種情況? 如果文件寫完之后沒有更新文件長度,默認(rèn)的文件長度是1個字節(jié),這個字節(jié)是一個隨機(jī)數(shù)。
因為是SEC_WRITE,所以一次寫64個字節(jié),而我第一次寫完64個字節(jié)就得到了1F。 明白了,如果讀到1F,我的程序就掛起了,沒有執(zhí)行后續(xù)CLOSE_FILE(包括更新文件長度)操作,所以文件長度為1,并且是隨機(jī)數(shù)。 用WINHEX看了自己試過的兩個U盤,都是512 bytes/sector。量了一下USB引腳電壓,4.89V與3.27V。應(yīng)該不會有什么問題吧,字節(jié)操作都正常的。
如果字節(jié)寫是正常 那就不應(yīng)該是硬件問題, 扇區(qū)寫做好參考官方提供的例程,下載CH376EVT.ZIP 參考CH376EVT\EXAM\EXAM8
完全是按那個例子來的。
for ( err = 0; err != 3; ++ err ) { /* 出錯重試 */ xWriteCH376Cmd( CMD5H_DISK_WRITE ); /* 向USB存儲器寫扇區(qū) */ xWriteCH376Data( (UINT8)iLbaStart ); /* LBA的最低8位 */ xWriteCH376Data( (UINT8)( (UINT16)iLbaStart >> 8 ) ); xWriteCH376Data( (UINT8)( iLbaStart >> 16 ) ); xWriteCH376Data( (UINT8)( iLbaStart >> 24 ) ); /* LBA的最高8位 */ xWriteCH376Data( iSectorCount ); /* 扇區(qū)數(shù) */ xEndCH376Cmd( ); for ( mBlockCount = iSectorCount * DEF_SECTOR_SIZE / CH376_DAT_BLOCK_LEN; mBlockCount != 0; -- mBlockCount ) { /* 數(shù)據(jù)塊計數(shù) */ s = Wait376Interrupt( ); /* 等待中斷并獲取狀態(tài) */ if ( s == USB_INT_DISK_WRITE ) { /* USB存儲器寫數(shù)據(jù)塊,請求數(shù)據(jù)寫入 */ CH376WriteHostBlock( buf, CH376_DAT_BLOCK_LEN ); /* 向USB主機(jī)端點的發(fā)送緩沖區(qū)寫入數(shù)據(jù)塊 */ xWriteCH376Cmd( CMD0H_DISK_WR_GO ); /* 繼續(xù)執(zhí)行USB存儲器的寫操作 */ xEndCH376Cmd( ); buf += CH376_DAT_BLOCK_LEN; } else break; /* 返回錯誤狀態(tài) */ } if ( mBlockCount == 0 ) { s = Wait376Interrupt( ); /* 等待中斷并獲取狀態(tài) */ if ( s == USB_INT_SUCCESS ) return( USB_INT_SUCCESS ); /* 操作成功 */ } if ( s == USB_INT_DISCONNECT ) return( s ); /* U盤被移除 */ CH376DiskReqSense( ); /* 檢查USB存儲器錯誤 */ }
分析下來,當(dāng)執(zhí)行完DISK_WRITE(0x56),并輸入四字節(jié)LBA和扇區(qū)數(shù)后,中斷得到0x1E,即通知FPGA開始寫64個字節(jié)的內(nèi)容,問題出在寫完64個字節(jié)后,返回的錯誤代碼是0x1F,存儲設(shè)備操作失敗,那應(yīng)該是寫U盤失敗。就是在第二次執(zhí)行紅色的代碼時判斷條件結(jié)果為假。正常情況應(yīng)該還是返回0x1E,讓我寫完后面的內(nèi)容,一次扇區(qū)至少要寫512字節(jié)吧。
有新發(fā)現(xiàn)。 雖然扇區(qū)只寫了64個字節(jié),并且返回錯誤信息,但我將軟件改成出錯強(qiáng)制關(guān)閉文件并且更新文件長度后, 得到了一個4096字節(jié)的文件,內(nèi)容很豐富,但沒有一個是我想要的。文件長度是對的,因為我的試驗程序?qū)懥?個SECTOR,共8*512=4096。 雖然是亂碼,但里面有些有趣的東西,比如有SETUP.EXE、config.ini、readme.txt等字符。這個U盤是完全格式化后再接CH376上的,應(yīng)該是干干凈凈的,我也只是在根目錄下存?zhèn)€N.TXT一個文件,這些內(nèi)容既然不是FPGA寫進(jìn)去的,那么究竟是哪里來的呢?
計算機(jī)格式化U盤,并不是把所有的扇區(qū)都清零,而是在文件的目錄項中作了一個標(biāo)志 表示該文件被刪除。實際上文件的內(nèi)容還在,計算機(jī)上看不到而已,所有即使U盤被格式化了 數(shù)據(jù)也有可能會被恢復(fù)。 這種修改文件長度的方法是不對的。 只會把一些無效的數(shù)據(jù)包含在文件中,參考下面的代碼修改一下 LPC2214下面的例程。UploadImages/20111715305665.rar
另外你可以再次測試一下你的程序在字節(jié)模式下是否仍然可以。如果可以的話,你移植一下扇區(qū)的讀寫函數(shù)即可,應(yīng)該問題不大。
那個ARM的文件我也已經(jīng)參考過了,與單片機(jī)的幾乎是一樣的。 現(xiàn)在問題的焦點在于:為了什么用WR_HOST_DATA命令將64個字節(jié)(固定為0x30,即字符“0”)寫到主機(jī)端點后,沒有成功寫到存儲設(shè)備即U盤上。 十分感謝_study_的幫助,我把FPGA捉到的完整的實際時序圖傳上來,有勞您或其他大俠分析分析。這關(guān)沖過去,可能后面就一順到底了。 UploadImages/20111715533920.rar 說明:圖中數(shù)據(jù)總線=FF表示讓總線高阻,準(zhǔn)備接收數(shù)據(jù),而非輸出數(shù)據(jù)0xFF。原理同單片機(jī)IO=1時方能讀入狀態(tài)一樣。
回復(fù):紅桃六 我試了一下,字節(jié)模式下仍然OK。 我也是對照著EXAM8,一步步移植過來的,當(dāng)初字節(jié)模式非常順利。 現(xiàn)在扇區(qū)模式前面也很順序,就是卡在了上面說的那一步,反復(fù)檢查得不到結(jié)果。
把代碼發(fā)過來看看,A0信號線默認(rèn)為低電平,寫完命令之后把A0拉低
這個問題還真有點難度。 根據(jù)_study_的建議,A0信號改為平時常為低,只在發(fā)命令時變高,原來我是平時為高,讀寫數(shù)據(jù)是為低。但改過來后結(jié)果一樣。
自己又進(jìn)了一步,當(dāng)?shù)玫?F(存儲設(shè)備操作失?。┑腻e誤碼后,執(zhí)行5A命令(檢查存儲器錯誤),CH376中斷后告訴我指令執(zhí)行成功,我再執(zhí)行CMD_RD_USB_DATA0,CH376告訴我有18個字節(jié)的錯誤代碼,用FPGA抓了: 0xF0,0x00,0x05,0x00,0x00,0x00,0x00,0x0A,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00 數(shù)據(jù)手冊上沒有找到錯誤代碼的說明,還請高手幫忙分析。 源碼是VHDL的,不過很容易讀,用了最笨但最可靠的方法,就是用狀態(tài)機(jī)生成各種操作時序。全部通過后我會做優(yōu)化工作,讓程序更符合規(guī)范的。 附件中還有實際捉到的時序圖。 UploadImages/20111811361294.rar
另外,在一開始,我沒有用CH376DiskConnect( )來檢查U盤是否連接,因為開機(jī)時U盤一定是插好的,另外,從ACT#腳上接的LED應(yīng)該也可以看出是否正常連接。同時也沒有檢查U盤的剩余空間。原來字節(jié)模式我也都沒有檢查,應(yīng)該沒有關(guān)系吧。我仔細(xì)分析了一下,與EXAM8就這一點區(qū)別了。 還有一個發(fā)現(xiàn)就是文件新建后,執(zhí)行扇區(qū)寫命令時,CH376會自動分配起始扇區(qū)號。但這個扇區(qū)號并不對應(yīng)實際U盤上文件的起始扇區(qū)號,而是后移了64個扇區(qū)。我強(qiáng)制把數(shù)據(jù)寫到實際文件起始的扇區(qū)位置,還是返回1F。
CMD0H_DISK_MOUNT(0x31)命令有沒有測試通過? 另外對于高速MCU來說,命令式數(shù)據(jù)之間要有2-4uS的延時,數(shù)據(jù)和數(shù)據(jù)之間也要有1-2us的延時
0X31過的,一直到寫入64字節(jié)命令都是全部正常通過的。延時時序一定能保證。 翻了一天的老貼子,有所發(fā)現(xiàn)。并不是我一個人會遇到這個問題。但他們大部分發(fā)了幾次后再出現(xiàn)錯誤的,0x1F,是所有用使用CH376工程師的惡夢之一。 有的說換U盤就好了,可是現(xiàn)在我手頭只有兩個U盤,一個是最普遍的“KINGSTON(4G)”,還有個“SSK(2G)”。兩個都可以進(jìn)行字節(jié)操作,如果紅桃的說法正確,那么肯定也支持扇區(qū)。而且CH376對U盤有90%的支持率,我想我的運氣不會那么差吧。兩個正好都是那個十分之一。 老貼子中有一篇是說一定要先獲取U盤剩余空間后再進(jìn)行操作。不知道是不是硬件規(guī)定。今天修改程序再看一下。
讀出了總扇區(qū)數(shù)和剩余扇區(qū)數(shù),與WINHEX得到結(jié)果完全一樣。FAT類型為03,數(shù)據(jù)手冊上查不到,應(yīng)該是FAT32吧。 但是結(jié)果還是一樣。第一個64字節(jié)就寫不進(jìn)去。 下一步,自己放個文件,看看扇區(qū)讀能不能操作。 其實關(guān)鍵是我在第12樓得到的那串錯誤代碼,我來聯(lián)系一下WCH的技術(shù)支持,看看能不能有所發(fā)現(xiàn)。