|
这几天研究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
- (
- /* [IN] 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位来存放才可以执行,而这条语句就是将低三位清零,得到一个对齐的地址,然后再操作!
其实说起来蛮简单的,但用起来很方便的,希望能给大家提提神! |
阿莫论坛20周年了!感谢大家的支持与爱护!!
你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。
|