各位看官,在看EFM32的MSC里面的函数时,例如在看MSC_ErasePage()这个函数的时候,有否注意这个函数上面的一大段解释呢。详细的英文如下:
This function MUST be executed from RAM. Failure to execute this portion of the code in RAM will result in a hardfault. For IAR, Rowley and Codesourcery this will be achieved automatically. For Keil uVision 4 you must define a section called "ram_code" and place this manually in your project's scatter file.
大致上的意思是,这个函数必须在RAM中执行。如果在不在RAM中执行的话,会产生硬件错误中断即Hardfault。 如果使用IAR, Rowley, Codesourcery,这个函数会自动在RAM中执行,而在Keil uVersion4中,则必须定义个叫做"ram_code"的段,并在项目的scatter 文件中申明。
首先为什么IAR等可以自动在RAM中执行呢?
1.IAR提供了__ramfunc,这个关键字,他会把函数自动拷贝到RAM中执行。在efm32_msc.h中对MSC_ErasePage()函数的定义如下:
__ramfunc msc_Return_TypeDef MSC_ErasePage(uint32_t *startAddress);
2.类似,在Rowley中,定义如下:
msc_Return_TypeDef MSC_ErasePage(uint32_t *startAddress) __attribute__ ((section(".fast")));
3.类似,在Codesourcery,定义如下:
msc_Return_TypeDef MSC_ErasePage(uint32_t *startAddress) __attribute__ ((section(".ram")));
三种定义各有不同,但是都实现了函数在RAM中执行的效果。而且也无需用户设置。
在Keil的目前版本中,就比较麻烦,举个例子来说,例如想在G STK上对操作的话,需要对Keil的工程配置中的Linker做一定的修改。具体示例如下:
1.取消Use Menory layout from Target Dialog 选项
2.在Scatter file中选择自定义的.sct文件。
接下来,我们可以看一下,这个文件里面定义了什么。
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x00000000 0x00020000 { ; load region size_region
ER_IROM1 0x00000000 0x00020000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00004000 { ; RW data
.ANY (+RW +ZI)
*(ram_code)
}
}
里面定义了ROM的地址,RAM的地址,但是多定义了一个叫做ram_code的东东。这个ram_code就是将那几个MSC里面的操作函数放到RAM里面的定义了。
各位看官可以拷贝这段信息,再根据自己的型号进行修改,然后保存为.sct 文件即可。然后通过Keil加载进来。
但是为什么非的要拷贝到RAM中执行呢?原因是因为在擦写Flash的时候,是不能对Flash进行操作的。而且擦写Flash需要一定的时间去操作。在我们的函数中,会使用代码去读取MSC相关的寄存器,然后判断操作是否完成。因此这里会有一个悖论就是,你既需要运行代码去判断是否完成,又不能在Flash中运行代码,所以,一个解决办法就是在RAM中运行喽。