资料分享:MQX中的函数从Flash中拷贝到RAM中的一种方法
这几天研究MQX的Flashx的驱动,在里面发现了一种函数拷贝的方法,以前没这么用过,觉得很有意思,发出来与大家分享,闲话少说,正题开始!在Flash操作的时候,有需要在RAM中运行等待指令,在MQX中函数定义如下:
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name : ftfl_ram_function
* Returned Value : void
* Comments :
* Code required to run in SRAM to perform flash commands.
* All else can be run in flash.
* Parameter is an address of flash status register.
*
*END*-----------------------------------------------------------------------*/
static void ftfl_ram_function
(
/* Flash info structure */
volatile uint8_t *ftfl_fstat_ptr
)
{
/* start flash write */
*ftfl_fstat_ptr |= FTFL_FSTAT_CCIF_MASK;
/* wait until execution complete */
while (0 == ((*ftfl_fstat_ptr) & FTFL_FSTAT_CCIF_MASK))
{ /* void */ }
}
static void ftfl_ram_function_end(void)
{}
这么定义的函数,他保存肯定是在Flash中,怎么样能把它搬到RAM中呢?我们看看他的运输函数:
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name : ftfl_init_ram_function
* Returned Value : pointer to allocated RAM function
* Comments :
* Allocate and copy flash RAM function.
*
*END*-----------------------------------------------------------------------*/
char *ftfl_init_ram_function
(
char *function_start,
char *function_end
)
{
char *ram_code_ptr;
_mem_size ftfl_ram_function_start;
/* remove thumb2 flag from the address and align to word size */
ftfl_ram_function_start = (_mem_size)function_start & ~3;
/* allocate space to run flash command out of RAM */
ram_code_ptr = _mem_alloc_align((char *)function_end - (char *)ftfl_ram_function_start, 4);
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (ram_code_ptr == NULL)
{
return NULL;
}
#endif
/* aopy code to RAM buffer */
_mem_copy ((char *)ftfl_ram_function_start, ram_code_ptr, (char *)function_end - (char *)ftfl_ram_function_start);
/* adjust address with respect to the original alignment */
ram_code_ptr = (char *)((_mem_size)ram_code_ptr | ((_mem_size)function_start & 3));
return ram_code_ptr;
}
下面是开始搬运:
flash_execute_code_ptr = ftfl_init_ram_function((char *)ftfl_ram_function, (char *)ftfl_ram_function_end);
我分析了一下上面的代码,发现这是利用了编译器顺序排放函数的特点,首先先定义了一个ftfl_ram_function函数,然后在紧跟着它的后面再放一个名为ftfl_ram_function_end的空函数,这样在编译器编译完后,产生的BIN中ftfl_ram_function函数的代码范围就是从ftfl_ram_function地址开始,到ftfl_ram_function_end地址结束,这就给搬运时把起始位置与长度定义了,再要做的事情无非就是将这段代码拷贝到RAM中运行就可以了。
说起拷贝,我们看到ftfl_init_ram_function函数中一开始并没有直接拷贝,而是有下面这样的语句:
ftfl_ram_function_start = (_mem_size)function_start & ~3;
那么这个语句又是干什么的呢?呵呵,其实很简单,它是做对齐的,因为ARM的指令级是32位的,它产生的代码当然要按32位来存放才可以执行,而这条语句就是将低三位清零,得到一个对齐的地址,然后再操作!
其实说起来蛮简单的,但用起来很方便的,希望能给大家提提神! 楼主的经验分享都是经过实际验证的,非常好。 谢谢分亨哈,学习学习。 zndz410 发表于 2014-5-15 11:38
谢谢分亨哈,学习学习。
不用客气,呵呵,技术是公有的,产品是私有的,技术共享是应该的! 好文章,推荐! 本帖最后由 wangpengcheng 于 2014-9-1 21:45 编辑
fengyunyu 发表于 2014-9-1 21:38
好文章,推荐!
我也觉得这个办法比较好玩,不用做数组,呵呵! 这个方法我也考虑过,没想到在这里找到了呢,很好! 学习啦,感谢楼主分享。 sunnyqd 发表于 2014-9-1 21:47
这个方法我也考虑过,没想到在这里找到了呢,很好!
MQX中的,呵呵,我也是现学现卖! mark
页:
[1]