通过函数指针来实现外部程序访问

        众所周知单片机的程序一般是运行在内部flash上的,然而内部一般是不允许外部访问的,当那么当你想通过单片机访问外部程序该怎么实现呢。最好的办法是通过XIP来跳转到外部flash上运行成外部程序,但是XIP需要MCU支持,所以这个方法下次讨论。不支持XIP的芯片的话,我们想到把程序搬运到RAM里面运行是否可行呢?

        首先我们需要规划一片区域,禁止其他程序访问,把我们需要的外部程序搬运在此位置。以便固件查找运行,那么怎么规划一片区域呢,此时我们需要用到KEIL上的一个叫(分散加载)的功能。当然分散加载的强大远不止,感兴趣的可以自行去查找

1.打开keil找了Linker将Use Memory Layout from Target Dialog 的勾选去掉,去掉勾选的目的是用我们自己的分散加载文件来定位程序,

去除Use Memory Layout from Target Dialog之后Targe里的内存分配将会失效,下面这个表分配的内存将会失效

2.编写自己的分散加载文件

        在这个页面下点击Edit编辑sct文件如果没有则自己创建一个

LR_IROM1 0x10000000 0x0003E000  {    ; load region size_region
  ER_IROM1 0x10000000 0x0003E000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  } 

  EXPORT_TB 0x200017a0 0x00000200  { ; 此段存放导出函数, 512字节, 一共可以放128个函数地址
   *.o (.export_tb)
  }

  EXTERN_EXEC 0x200019a0 0x00001000 { ; 外部模块加载到这里执行
   .ANY (.extern_exec)
  }
  
  RW_IRAM1 0x200029a0 0x00005660  {  ; RW data
   .ANY (+RW +ZI)
  }
}

 第一部分为系统的RO段(不懂的自己百度),0x200017a0这个地址开辟了512个字节的空间来放我们提供给外部程序的API接口, 0x200019a0这个地址开辟了一个4K的大小来存放外部程序,0x200029a0存放所有的RW和ZI段包括外部程序的。此时我们已经把所需要的程序空间开辟好了。

三给外部程序提供api接口这里只用一个API来演示

typedef void (*export_api_t)(void);
uint16_t GetLibraryVersion(void)
{
	return 0x0080;	//0.0.1.0
}

const export_api_t export_apis[] __attribute__((__used__)) __attribute__((__section__(".extern_exec"))) = 
{
	(export_api_t)GetLibraryVersion,	//获取版本号
};

        首先我们typedef一个函数指针 ,然后用函数指针来定义一个,函数指针数组,函数指针数组用来存放我们需要给外部程序调用的API,将程序中的函数用函数指针申明后存放再数组

__attribute__((__used__)) __attribute__((__section__(".export_tb"))) 这个句话的意思是将数组定位在.export_tb段,并且used告诉程序我已经使用了你不要再用这个地方的内存了,.export_tb此段内存为我们最开始的sct文件中定义的

3.实现外部程序访问

        重新定义一个函数指针,定义一个buff来存放外部程序,同上一样指定在固定块

typedef void (*pFunction)(void);
pFunction JumpToApplication;

/* Applet代码执行区 */
uint8_t extern_exec_ram[4096] __attribute__((__used__)) __attribute__((__section__(".extern_exec"))) ;

 把外部flash的数据拷贝到数组中,我存放数据的地址放在0x01700000上flash做了内存映射所以可以直接读取,用flash_read();也是一样的我们的目的是把数据读出来,然后将内存的数据转换成函数用JumpToApplication 来接收,最后运行函数

    uint32_t *p_ram = (uint32_t *)extern_exec_ram;
    uint32_t *p =  (uint32_t*) (0x01700000);

	for(int i = 0; i < 1024; i++)
	{
		*p_ram = *p;
		p++;
		p_ram++;
	}
	
	JumpToApplication = (pFunction)(extern_exec_ram + 1);
	JumpToApplication();

至此 MUC的主程序部分已经弄好了,之后我们需要弄下载程序,这个下篇在来说明

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值