2015-12-08 33 views
1

我目前正在開發基於Atmel的at91sam7s256 MCU的器件功能。該功能是具有預設值的計數器,在某些點上會減少。 我的想法是在內部閃存中實現此計數器,因爲大部分閃存空間都未使用。在內部寫入at91sam7s256閃存

我在ld腳本中添加了一個單獨的鏈接器部分,並在此部分包含了一個變量。鏈接描述:當計數器減

/* 
    FLASH is reserved for internal settings 
*/ 

MEMORY 
{ 
    CODE (rx) : ORIGIN = 0x00100000, LENGTH = 252k 
    FLASH (rx) : ORIGIN = 0x0013F000, LENGTH = 4k 
    DATA (rwx) : ORIGIN = 0x00200000, LENGTH = 64k 
} 
__FIRST_IN_RAM = ORIGIN(DATA); 
__TOP_STACK = ORIGIN(DATA) + LENGTH(DATA); 

/* Section Definitions */ 

SECTIONS 
{ 
    /* first section is .text which is used for code */ 
    . = ORIGIN(CODE); 

    .text : 
    { 
     KEEP(*(.vectorg)) 
     . = ALIGN(4); 
     KEEP(*(.init)) 
     *(.text .text.*)     /* remaining code */ 
     *(.gnu.linkonce.t.*) 
     *(.glue_7) 
     *(.glue_7t) 
     *(.gcc_except_table) 
     *(.rodata)     /* read-only data (constants) */ 
     *(.rodata.*) 
     *(.gnu.linkonce.r.*) 
     . = ALIGN(4); 
    } >CODE 


    . = ALIGN(4); 

    /* .ctors .dtors are used for c++ constructors/destructors */ 

    .ctors : 
    { 
     PROVIDE(__ctors_start__ = .); 
     KEEP(*(SORT(.ctors.*))) 
     KEEP(*(.ctors)) 
     PROVIDE(__ctors_end__ = .); 
    } >CODE 

    .dtors : 
    { 
     PROVIDE(__dtors_start__ = .); 
     KEEP(*(SORT(.dtors.*))) 
     KEEP(*(.dtors)) 
     PROVIDE(__dtors_end__ = .); 
    } >CODE 

    . = ALIGN(4); 

    _etext = . ; 
    PROVIDE (etext = .); 

    /* .data section which is used for initialized data */ 
    .data : AT (_etext) 
    { 
     _data = . ; 
     KEEP(*(.vectmapped)) 
     . = ALIGN(4); 
     *(.fastrun .fastrun.*) 
     . = ALIGN(4); 
     SORT(CONSTRUCTORS) 
     . = ALIGN(4); 
     *(.data) 
     *(.data.*) 
     *(.gnu.linkonce.d.*) 
     . = ALIGN(4); 
    } >DATA 

    . = ALIGN(4); 

    _edata = . ; 
    PROVIDE (edata = .); 

    /* .bss section which is used for uninitialized data */ 
    .bss (NOLOAD) : 
    { 
     __bss_start = . ; 
     __bss_start__ = . ; 
     *(.bss) 
     *(.bss.*) 
     *(.gnu.linkonce.b.*) 
     *(COMMON) 
     . = ALIGN(4); 
    } >DATA 

    . = ALIGN(4); 

    __bss_end__ = . ; 

    .flash : 
    { 
     . = ORIGIN(FLASH); 
     *(.flash*) 
     . = ALIGN(4); 
    } >FLASH 


    _end = .; 
    PROVIDE (end = .); 
} 

以下例程用於:

#define INTERNAL_FLASH __attribute__((section(".flash"))) 

#define AT91C_MC_WRITE_KEY ((unsigned)0x5A << 24) // Magic number 

INTERNAL_FLASH uint32_t Counter = 30; // The section .flash begins at 0x0013F000 

void prepaid_decrement(void) 
{ 
    if(Counter > 0) { 
     // write into buffer 
     Counter = Counter - 1; 

     volatile AT91PS_MC mc = AT91C_BASE_MC; 
     // set flash mode (timing) 
     mc->MC_FMR = AT91C_MC_FWS_1FWS | ((1 + (((MCK * 15)/10000000))) << 16); 

     uint32_t page = ((uint32_t)&Counter - (uint32_t)AT91C_IFLASH)/(uint32_t)AT91C_IFLASH_PAGE_SIZE; 

     // start writing 
     mc->MC_FCR = AT91C_MC_WRITE_KEY | AT91C_MC_FCMD_START_PROG | (page << 8); 
     if(0 != (mc->MC_FSR & AT91C_MC_PROGE)) {TRACE("error!");} 

     while (!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY)); 
    } 
} 

但代碼掛在 mc->MC_FCR = AT91C_MC_WRITE_KEY | AT91C_MC_FCMD_START_PROG | (page << 8);。下面的行永遠不會到達,因爲MCU跳轉到異常循環(向量表中的地址0x60)。

無論如何,數據似乎被正確寫入,因爲重置後計數器變量減少了一個。

誰能告訴我我做錯了什麼?代碼沒有被打斷。

+0

「計數器=計數器-1」嘗試寫入閃存中的地址,該地址最可能是隻讀區域。你沒有粘貼你的鏈接腳本。 – mkmk88

+0

該變量鏈接到該部分開頭的固定地址。這意味着(buffer-)變量是可寫的,也可以通過調用寫入命令寫入閃存。但不知何故,它掛在這個命令,雖然閃光燈已經寫好。 – eeucalyptus

+0

我沒有使用這個特定的MCU,但根據文檔:http://www.atmel.com/Images/doc6175.pdf內部閃存介於0x00100000和0x001FFFFF之間。您的代碼指示將變量「counter」放入「.flash」部分。源代碼中的註釋指出,「.flash」在0x0013F000處,這實際上是內部閃存。本節最可能是隻讀的。沒有看到你的鏈接腳本,我不能幫助更多。 – mkmk88

回答

2

該代碼導致一個異常,因爲它在嘗試編程閃存時正在執行閃存。一旦寫入閃存模式寄存器,就不能再從閃存中讀取指令。編程閃存的功能應放置在RAM中。