2014-07-17 71 views
3

我遇到的問題是PIC32MX795F512L的引導加載程序正在工作。Pic32引導加載程序寫入內存

我基於微芯片網站上的示例代碼。

下面是我應該編寫內存的代碼段,我已經驗證了引導加載程序到目前爲止(解析十六進制文件就好了,數據到達了這一點,但沒有寫入內存):

#define NVMOP_WORD_PGM   0x4001 


// Write the data into flash. 
Result = NVMemWriteWord(ProgAddress, WrData); 
// Assert on error. This must be caught during debug phase. 
if(Result != 0) 
{  
    ASSERT(Result==0); 
} 

UINT NVMemWriteWord(void* address, UINT data) 
{ 
    UINT res; 

    NVMADDR = KVA_TO_PA((unsigned int)address); 

    // Load data into NVMDATA register 
    NVMDATA = data; 

    // Unlock and Write Word 
    res = NVMemOperation(NVMOP_WORD_PGM); 

    return res; 
} 

UINT __attribute__((nomips16)) NVMemOperation(UINT nvmop) 
{ 
    int int_status; 
    int susp; 

    // Disable DMA & Disable Interrupts 
    #ifdef _DMAC 
    int_status = INTDisableInterrupts(); 
    susp = DmaSuspend(); 
    #else 
    int_status = INTDisableInterrupts(); 
    #endif // _DMAC 

    // Enable Flash Write/Erase Operations 
    NVMCON = nvmop;//NVMCON_WREN | nvmop; 
    // Data sheet prescribes 6us delay for LVD to become stable. 
    // To be on the safer side, we shall set 7us delay. 
    delay_us(7); 

    NVMKEY  = 0xAA996655; 
    NVMKEY  = 0x556699AA; 
    NVMCONSET = NVMCON_WR; 

    // Wait for WR bit to clear 
    while(NVMCON & 0x8000);//NVMCON_WR); 

    // Disable Flash Write/Erase operations 
    NVMCONCLR = NVMCON_WREN; 


    // Enable DMA & Enable Interrupts 
    #ifdef _DMAC 
    DmaResume(susp); 
    INTRestoreInterrupts(int_status); 
    #else 
    INTRestoreInterrupts(int_status); 
    #endif // _DMAC 

    // Return Error Status 
    return(NVMemIsError()); 
} 

的一個程序地址的正被裝入實施例是:用0x9D033358數據是2403000E

配置位被設置在代碼和如下:

地址設置

1FC02FF0 FCFFFFFF

1FC02FF4 FFF8FFDF

1FC02FF8 FF69CC5B

1FC02FFC 7FFFFFFF

不能告訴你什麼都做位,但閃光燈位被設置爲可寫和代碼保護是禁用。

+0

在嘗試執行程序字(寫入)操作之前,您是否執行了擦除塊操作? –

+0

謝謝。解決了這個問題。添加一個答案,我可以+1你 – user2076574

+1

這是一個錯誤發佈問題的解決方案。請張貼它作爲你自己的答案。回答自己的問題是可以的。 –

回答

4

閃存與普通RAM的工作方式不同。爲了寫入它,你首先需要擦除你想寫的塊。這將塊中的所有位設置爲1.然後可以使用編程操作將1位更改爲0位。沒有寫操作將位設置爲0或1,您必須將這兩個操作組合起來以獲得相同的效果。

請注意,可以在不先擦除的情況下執行編程操作。它將繼續工作,它會將1位更改爲0位。但是,由於它不能將已編程的0位更改爲1位,因此可能無法獲得所需的結果。

有一點需要注意的是,擦除操作會損壞閃存,並將其慢慢磨損。 datasheet for your controller僅在失敗之前列出至少1000個擦除/寫入週期。這對於定期更新固件和配置值來說已經足夠了,但如果使用它來存儲頻繁更新的數據可能還不夠。

+0

IMO,OP應該已經接受了這個答案。它很好地回答了現在編輯出來的「所以任何想法,爲什麼這不會寫入記憶?」 – chux

2

解決方案(感謝羅斯嶺): 所以埋在資料片筆記有與說你需要寫前擦除存儲器中的頁面擦除命令的註釋。

添加以下來解決該問題(命令被稱爲做任何內存之前寫入):

#define FLASH_PAGE_SIZE 4096 
void StartLoad(void) 
{ 
    int Address = APP_FLASH_BASE_ADDRESS; 

    RxBuff.Len = 0; 

    while((Address + FLASH_PAGE_SIZE) <= APP_FLASH_END_ADDRESS) 
    { 
     NVMemErasePage(Address); 
     Address += FLASH_PAGE_SIZE; 
    } 
} 

UINT NVMemErasePage(void* address) 
{ 
    UINT res; 

    // Convert Address to Physical Address 
    NVMADDR = KVA_TO_PA((unsigned int)address); 

    // Unlock and Erase Page 
    res = NVMemOperation(NVMOP_PAGE_ERASE); 

    // Return WRERR state. 
    return res; 

} 

下面的鏈接也是有幫助的,它列出了Flash頁面大小爲所有Pic32s第10頁和11: http://ww1.microchip.com/downloads/en/DeviceDoc/61145K.pdf