• 已解决 73482 个问题
  • 已帮助 5993 位优秀工程师

stm32能否做到内核与应用程序分离(用动态链接库?

32438cbf52c0fb41 2020-06-16 浏览量:2536

希望在stm32上实现系统与应用程序分离的机制(虽然没有MMU)

stm32有个从sd卡运行python的项目,没试过,或许与我下面的设想2相符

 

我们通常所做的单片机系统都是整个系统只运行一个程序,我希望能实现系统Kernel部分可以根据需要从SD卡启动应用程序,最好是能运行多个应用程序,并且最初的Kernel部分不会被覆盖。

 

我设想的方法:
1、bootloader与app分离

我以前做过stm32 bootloader升级系统,姑且把上面的应用程序分为两部分:

- 20K bootloader 存放于0x00000000,中断向量表0x00000000
- 余下 app(实际系统) 存放于0x00000000+20K,中断向量表0x08000000

 

当bootloader启动app部分后,bootloader的中断向量部分被新的覆盖,似乎投胎一样,system感知不到bootloader,两个部分都有USART驱动,都重复编写printf,很麻烦。app部分需要维护中断、应用程序、维护中断向量表。

 

2、借助动态链接库采用ucos、rt-thread等RTOS的任务方式

我以前写过静态链接库供keil在其他项目里编译,动态链接库没做过。设想如下:

首先编译Kernel部分,包含系统所有的驱动、中断、内存管理,然后将API导出(这个我不会),导出的内容如同linux源码里的System.map文件一样,Kernel的加载地址是0x00000000

```
c0020d4c t atkbd_init
c0020d74 t gpio_keys_init
c0020d90 T bl_key_init
c0020e68 t psmouse_init
c0020efc T synaptics_module_init
c0020f1c t mxs_ts_init
```

编译app,加载地址是0x08000000,它只管理应用功能,对于硬件控制从系统的API获取。app作为rtos的线程运行。

3、多app运行

或许实现不了,stm32没有mmu,app的加载地址是0x08000000,若启动第二个app,如何能避免不于第一个app冲突

0 0 收起

我来回答

上传资料:
选择文件 文件大小不超过15M(格式支持:doc、ppt、xls、pdf、zip、rar、txt)
所有亮答 数量:6
  • STM32的库都是要先编译好,再添加到工程中,大多是静态库

    你说的分层,其实很多RTOS也都是 这个理念的,只是进行了一级的API封装,看上去是分层的,只是通过API进行底层的访问

  • 我想了想,bootloader加app可以。

    如果你不考虑效率的话,可以考虑解释性语言,比如python,lua

    动态链接是不现实的,​

  • 如果你能修改freertos的源码,理论上是可以实现的。所谓的操作系统,它就是维护着一个链表,所有的进程入口函数都是在这个链表上,当然还有进程的运行状态,堆栈,数据段等。因此只要将你的程序编译为二进制,并将入口放置到这个链表上,还是有可能的。不过STM32本身资源有限,这样做意义不大

  • 在stm32的实际环境中,做不到你想象的部分。

    现在类似的处理有内部加载一个虚拟机,然后再加载程序,比如MicroPython、lua,甚至javascript等等,反而C程序不行,因为这些需要编译,链接

    对于stm32类似开发,编译后都是静态链接输出,即使采用RTOS等,其仅仅是开发阶段的一种处理和封装,并不是运行阶段的动态加载。

  • st的gui库不就是以库的形式来支持的,所以,库的方式是很方便的

  • 这个可以做到,而且技术上并不难,实际上你说的是两个问题,一个是iap升级APP之后,两个都是完整的程序,驱动都是两份,这个可以做成一份,我做过iap带驱动,但是驱动的所有需要app调用的函数,在iap中定义了一个指针数组,里面以此存放了app那边需要调用的函数,而这个数组的起始地址,是写死的,这样子,切换到app那边,app使用函数的时候,定义一个结构体,结构体里面,结构体里面全部都是对应的函数指针,然后这个结构体在使用之前,创建一个,而地址强制指向iap那边写死的那个地址,这样子你就可以在使用的地方使用结构体中的数组调用对应的函数实体,而中断那边,也只需要在iap中断那边写一个中断回调,而回调实际上是在app这边填充的,这样中断之后,实际上也是调用了iap里面的那个中断地址,只是回调到这边执行,当然需要使用到的变量,我这边是强制定义了一片内存空间,两边都能访问到,这样子固化在flash中的函数用到的变量,app这边能正常使用,这就是驱动和应用程序分离,没这样做之前,我的app 20多KB,分离之后,app只有5KB,升级的时候也就很方便了,另外中断也可以用重定向的方式而不用回调的方式,当然我使用的国产M0芯片不支持重定向,所有我是直接设置一个标志位,当iap开机读取flash中的变量,然后去判断是否备份中断向量表,然后决定是否执行备份,如果没有备份就备份中断向量表,之后再判断是否有app,如果没有app就准备无线或者是串口接收app,接收完成app之后,在跳转之前,直接强制把app前面的中断向量表拷贝到iap的中断向量表这片flash区域,从而替换掉中断向量表,然后跳转app,这样子app运行之后,也可以正常使用它自己的中断向量表,当下次复位进入iap之后,iap又自动从备份分区复制自己的中断向量表,然后执行后面是直接跳转到app还是接收app数据,并且有自己完整的中断处理程序,这个方法可让任何低廉不支持中断重定向的mcu实现iap升级,

    当然你的第二个问题是想实现类似windows  Linux那样,直接下载app程序升级,这个也并不难,实际上iap就是实现了这个功能,但是你会发现跳转到自己下载的app之后就只能在app运行了,貌似不对劲,实际上你缺少了一个rtos,你只需要移植一个rtos就可以解决这个问题,同时你可以把所有的驱动注册到rtos的设备链表中,如果rtos不支持这些,那就传统的方式写好驱动以及系统调用的函数,导出一个符号表,然后你再利用这个符号表以及头文件,写你自己的应用app,写好之后编译好,再通过串口或者其他方式放入rtos的文见系统,如果没有文件系统,那就直接放入flash,或者直接放到缓存中,如果是放入flash中,当你数据发送完成之后,你需要把这段数据再次读到内存中,而这个内存的起始地址,实际上就是你这个app的运行地址,而rtos可以动态创建一个线程,函数的起始地址,就你这个缓存的起始地址,然后创建线程运行,这样子,你就可以不需要烧录完整的程序,类似Linux或者windows一样,编译自己的app。当然这个是rtos中运行,所有你需要会编写rtos的程序,可以利用rtos注册的驱动,直接使用驱动,直接写文件,直接发送消息给其他任务干一些别的事情,如果你实现了文见系统,网络,串口传输,你可以通过各种方式把你编译的app传输到文见系统中,然后编写一个读取函数,比如lnmod meapp,然后执行meapp这个app装载到内存中,创建线程,执行线程,rtos会自动运行,切换线程,让其看起来是并行运算,如果你没有rtos,你需要自己实现一个调度器简单的实现这些功能

相关问题

问题达人换一批

stm32能否做到内核与应用程序分离(用动态链接库?