内部写入at91sam7s256 flash
Write to at91sam7s256 flash internally
我目前正在为基于 Atmel 的 at91sam7s256 MCU 的设备开发一项功能。该功能是一个具有预设值的计数器,该值在某些点会减少。
我的想法是在内部闪存中实现这个计数器,因为大部分闪存 space 未被使用。
我在 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 跳入异常循环(向量 table 中的地址 0x60)。
无论如何,数据似乎是正确写入的,因为重置后计数器变量减一。
谁能告诉我我做错了什么?代码没有被打断。
代码导致异常,因为它在尝试对闪存编程时正在闪存外执行。一旦闪存模式寄存器被写入,就不能再从闪存中读取指令。编程flash的函数应该放在RAM中。
我目前正在为基于 Atmel 的 at91sam7s256 MCU 的设备开发一项功能。该功能是一个具有预设值的计数器,该值在某些点会减少。 我的想法是在内部闪存中实现这个计数器,因为大部分闪存 space 未被使用。
我在 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 跳入异常循环(向量 table 中的地址 0x60)。
无论如何,数据似乎是正确写入的,因为重置后计数器变量减一。
谁能告诉我我做错了什么?代码没有被打断。
代码导致异常,因为它在尝试对闪存编程时正在闪存外执行。一旦闪存模式寄存器被写入,就不能再从闪存中读取指令。编程flash的函数应该放在RAM中。