【问题标题】:Write to at91sam7s256 flash internally内部写入at91sam7s256 flash
【发布时间】:2015-12-08 13:14:13
【问题描述】:

我目前正在为基于 Atmel 的 at91sam7s256 MCU 的设备开发一项功能。该功能是一个具有预设值的计数器,该值在某些点会减小。 我的想法是在内部闪存中实现这​​个计数器,因为大部分闪存空间都没有使用。

我在 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-&gt;MC_FCR = AT91C_MC_WRITE_KEY | AT91C_MC_FCMD_START_PROG | (page &lt;&lt; 8);。永远不会到达下面的行,因为 MCU 会跳入异常循环(向量表中的地址 0x60)。

无论如何,数据似乎被正确写入,因为在重置后计数器变量减一。

谁能告诉我我做错了什么?代码没有被中断。

【问题讨论】:

  • "Counter = Counter - 1" 尝试写入闪存中的地址,这很可能是只读区域。您没有粘贴链接描述文件。
  • 变量链接到节开头的固定地址。这意味着(buffer-)变量是可写的,也可以通过调用写命令将其写入闪存。但不知何故它挂在这个命令虽然闪存已经写入。
  • 我没有使用这个特定的 MCU,但根据文档:atmel.com/Images/doc6175.pdf 内部闪存介于 0x00100000 和 0x001FFFFF 之间。您的代码指示将变量“counter”放入“.flash”部分。您源代码中的注释指出,“.flash”位于 0x0013F000,实际上是内部闪存。本节很可能是只读的。如果没有看到您的链接器脚本,我无法提供更多帮助。
  • 根据文档,对闪存的写操作被应用到一个缓冲区。一旦调用写入命令,该缓冲区就会立即写入实际的闪存。所以我所做的是获取一个特定的闪存页面(第 1008 页)并在其开头写入变量。然后我调用 write 命令并将页面缓冲区写入内存。正如我所说,数据实际上是写入的,甚至可以在复位后读出。但控制器进入异常状态。
  • 啊哈,我明白了。那你读过doctort.org/adam/nerd-notes/arm-flash-memory.html吗?在 cmets 中也有人遇到过类似的问题。

标签: c arm embedded atmel flash-memory


【解决方案1】:

代码导致异常,因为它在尝试对闪存进行编程时在闪存之外执行。一旦闪存模式寄存器被写入,就不能再从闪存中读取指令。对 flash 进行编程的函数应该放在 RAM 中。

【讨论】:

    猜你喜欢
    • 2014-07-17
    • 2016-07-11
    • 2019-06-07
    • 2010-12-08
    • 2021-04-16
    • 2013-11-28
    • 2021-03-10
    • 2016-03-24
    • 1970-01-01
    相关资源
    最近更新 更多