AMLogic的8613 MBOX是一個非常不錯的視頻播放系統,穩定、成熟度高,成本也較低。其開發的AVOS應該是基于uC/OS內核做的,運行效率很高。其開發的模式也很有意思,沒有文檔,網上也找不著資料,只能手把手地教,甚至連它的開發環境也只能到其公司去安裝。開發過程中遇到問題是常有的事,有時只能自己摸索。前幾天我自己就遇到個SPI問題,在這里記錄一下供參考。
起因是換了一個開發板。這塊新板的SPI-Flash的型號跟原板不同,原板的是25x32VSIG,新板是N25S32-75HE,測試的結果是可以調試,但燒錄時瞬間假燒完成,重新上電沒反應。問AML那邊的支持,答曰可能不支持該型號,底層驅動的代碼只有原廠才有無法獲取修改,建議換SPI。
于是買了跟原板一樣的25x32SPI換上去,但不知是不是硬件不兼容,這次索性連調試都無法進行了,直接下載完就校驗出錯。把原板的SPI拖下來,焊到新板上,問題依舊。
換回新板N25S32的SPI,調試跟蹤,發現是打開SPI設備時出錯了,嘗試調用SPIGetDevice()獲取設備信息,結果是返回空。意思是沒有找到支持的SPI設備。因為系統支持的SPI已經在bsp.c里列明了,只支持以下幾種:
SPISupport(&spi_w25x16);
SPISupport(&spi_w25q16);
SPISupport(&spi_mx25l3205d);
SPISupport(&spi_w25x32);
SPISupport(&spi_w25x16V);
SPISupport(&spi_MX25L800);
SPISupport(&spi_en25b32b);
SPISupport(&spi_MX25L160);
SPISupport(&spi_en25f32b);
另外spi_flash.h里還有幾種SPI的聲明,但經測試加入系統后仍然無法識別N25S32。
為了探明SPI的識別原理,找出各型號SPI的區別,我寫了一個函數,將系統能支持的SPI的所有信息全打印出來。spi_flash.h里有SPI結構的定義:
typedef struct{
unsigned deviceId;
char* chipname;
unsigned chip_size; // chip size in byte
unsigned block_size;
unsigned sector_size;
SpiFlashOpResult (*erase_chip) (SpiFlashDevice *device);
SpiFlashOpResult (*erase_block)(SpiFlashDevice *device, unsigned block_num);
SpiFlashOpResult (*erase_sector)(SpiFlashDevice *device, unsigned sector_num);
SpiFlashOpResult (*write_address)(SpiFlashDevice *device, unsigned spiaddr, unsigned *src_addr, int len);
SpiFlashOpResult (*read_address)(SpiFlashDevice *device, unsigned spiaddr, unsigned *dest_addr, int len);
int (* get_sector_num)(SpiFlashDevice *device,unsigned spiaddr);
void *fs_offset;
unsigned fs_kb;
}SpiFlashChip;
其中很明顯,erase_chip、erase_block、write_address等函數是一樣的,在spi_flash.h里有相應的實現。我們只需要打印其它信息:
//added by huz
int spi_info_i=0;
void print_spi_info(const SpiFlashChip * spi)
{
if(spi==NULL)
{
printf("spi is null/n");
return;
}
spi_info_i++;
printf("spi_%d info :/n",spi_info_i);
printf("deviceId: %d (HEX:%X)/n",spi->deviceId,spi->deviceId);
printf("chipname: %s/n",spi->chipname);
printf("chip_size: %d/n",spi->chip_size);
printf("block_size: %d/n",spi->block_size);
printf("sector_size: %d/n",spi->sector_size);
printf("fs_offset: %X/n",((int)spi->fs_offset));
printf("fs_kb: %d/n/n",spi->fs_kb);
}
void print_spi_infos()
{
printf("by huz - spi infos:/n/n");
print_spi_info(&spi_w25x16);
print_spi_info(&spi_w25q16);
print_spi_info(&spi_mx25l3205d);
print_spi_info(&spi_w25x32);
print_spi_info(&spi_w25x16V);
...
print_spi_info(&spi_s25fl032p);
}
運行結果,在JTAG調試時輸出如下:
by huz - spi infos:
spi_1 info :
deviceId: 1388783 (HEX:1530EF)
chipname: WINBOND W25X16
chip_size: 2097152
block_size: 65536
sector_size: 4096
fs_offset: 1FF000
fs_kb: 4096
spi_2 info :
deviceId: 1392879 (HEX:1540EF)
chipname: WINBOND W25Q16
chip_size: 2097152
block_size: 65536
sector_size: 4096
fs_offset: 1FF000
fs_kb: 4096
spi_3 info :
deviceId: 1450178 (HEX:1620C2)
chipname: MX25L3205D
chip_size: 4194304
block_size: 65536
sector_size: 4096
fs_offset: 3FF000
fs_kb: 4096
spi_4 info :
deviceId: 1454319 (HEX:1630EF)
chipname: WINBOND W25X32
chip_size: 4194304
block_size: 65536
sector_size: 4096
fs_offset: 3FF000
fs_kb: 4096
spi_5 info :
deviceId: 1388783 (HEX:1530EF)
chipname: WINBOND W25X16V
chip_size: 2097152
block_size: 65536
sector_size: 4096
fs_offset: 1FF000
fs_kb: 4096
...
spi_17 info :
deviceId: 1376769 (HEX:150201)
chipname: SPANSION S25FL032P
chip_size: 4194304
block_size: 65536
sector_size: 4096
fs_offset: 3F0000
fs_kb: 65536
很顯然,deviceId和chipname是決定SPI型號用的,而deviceId應該是關鍵,每個SPI的deviceId都不一樣,系統初始化時應該是會把支持的SPI的deviceId輪詢一次,如果有響應的話則說明對應型號的SPI接到系統上了。
于是在網上查了下N25S32-75HE的資料,其中有設備ID的說明:
跟上述打印的信息一比較,顯然我們需要的設備ID是0x1630D5。于是手工增加了一個SPI的定義:
const SpiFlashChip spi_N25S32XX={
0x1630d5,
"QTHUZ N25S32",
(32/8)*1024*1024,
65536,
4*1024,
SPIEraseChip,
SPIEraseBlock,
SPIEraseSector,
SPIWrite,
SPIRead,
SPIGetSectorNum,
(void *) 0x3ff000,
4*1024, };
SPISupport(&spi_N25S32);
接著運行,發現用SPIGetDevice()確實能找到SPI了。于是修改了代碼,滿懷希望地開始燒錄,但最終仍然是寫入失敗,斷點停在一個寫參數的位置。
分析了一下原因,這時除了chipname,其它參數都是相當正確的。由于沒有SPI的驅動代碼,也無法判斷原因,只能猜測是AML做了什么手腳。
由于N25S32的芯片號稱是跟W25X32兼容的,于是我又想到,如果直接用W25X32的定義,強制在內存中修改其設備ID,也許可以騙過AML。說干就干,我在SPI初始化前加入以下代碼:
int devid=0x1630d5;
memcpy((void*)&(spi_w25x32.deviceId),(void*)&devid,4);
再次運行,用SPIGetDevice()獲取并打印SPI信息如下:
spi_1 info :
deviceId: 1454293 (HEX:1630D5)
chipname: WINBOND W25X32
chip_size: 4194304
block_size: 65536
sector_size: 4096
fs_offset: 3FF000
fs_kb: 4096
呵呵,W25X32的設備ID被修改成0x1630d5。接著修改代碼執行燒錄,這次終于燒錄成功:
>make prom
Using Sun Microsystems Inc. Java version 1.6.0_06 on Windows.
Welcome to the GUI version of the MetaWare Debugger, v8.2.5 (1362).
License SeeCode expires
USB JTAG Firmware (Ver1.04) / DLL (Ver1.05)
Parallel port driver (gportio.sys) version 4 (fast) detected.
ELF segment #0 addr 0x3800000 size 0x000130 .
ELF segment #1 addr 0x3800500 size 0x370b14 ................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
.........
ELF segment #1 addr 0x3b71014 zero 0x024f30 (program zeroes BSS)
[1] Progress display created was 10920e28
License SC_AC expires
Added by huz - Burn start...
spi_1 info :
deviceId: 1454293 (HEX:1630D5)
chipname: WINBOND W25X32
chip_size: 4194304
block_size: 65536
sector_size: 4096
fs_offset: 3FF000
fs_kb: 4096
by huz - open source: /dev/ramdisk0
by huz - loop segs
by huz - open target: /dev/spi
by huz - upgrade start...
upgrading in progress 99%
by huz - clean memory
by huz - exiting...
by huz - Burn OK, can power down now.
Shutting down all processes...Done
重新上電,終于在視頻輸出上看到親切的開機界面了。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
