本帖是系列贴,先是简单介绍一下,之后会有一些好玩的应用发布,不过基本也都只是基于我们的linux子系统,跑一些现成的linux应用代码,不过会把应用移植的来龙去脉讲了更加详细,平台可能是x86、STM32H743、全志D1、AIC8800M。
1年半之前,还是计划用ESP32来实现,不过由于没有任何技术支持,github里提issue也是半年后才有回复,所以就放弃了,ESP32的支持也一直没发布。
不过,这两年国产的wifi soc还是挺多的,我们评估过的也有好几家了,后来换了另外一家爱科微的AIC8800M。
实际使用下来还是不错的。虽然芯片文档还是比较缺,但有问题找原厂基本都很快会有回复,所以也比较顺利的搞定了,已经有几个项目量产了。
这里先简单介绍一下VSF和AIC8800M
VSF:
1. 事件驱动内核,从51支持到x64,还可以支持wasm,可以运行在RTOS的线程里,也可以运行在中断里。
2. 统一的应用开发方式,可以在PC上,用visual studio开发调试好应用之后,放在MCU的环境里编译使用。
3. 各种功能组件
4. 模拟其他OS,比如模拟成linux,直接使用一些Linux的应用代码
爱科微 AIC8800M:
1. 双频(2.4G/5G)Wifi6 + 双模(EDR/BLE)BT5
2. CortexM4F 240M 992K字节 sram 2M字节 flash,并且有型号内置4M字节psram
3. 480M主频 DSP
4. 1路 60MHz SPI,1路 I2C主,3路 UART,1路 USB OTG内置高速PHY,1路SDIO 主/从,I2S音频(AIC8800A内置codec),ADC,PWM。。。。
5. 5x5 QFN
我们之前评估了几家国产的wifi soc,开发基本都是FreeRTOS + lwip。不过esp-edf算是特例,虽然直接使用一些linux的应用会有一些问题,但是可以使用很多linux的API来开发,这个算是非常超前的了。结合我们自己的一些应用尝试,发现用linux的方式来开发wifi soc确实会非常方便,有很多现成的资源可以使用,仅仅需要注意,如果在产品上使用的话,尽量使用一些非GPL许可的软件,比如libcurl、libsdl啥的。也问过一些用户,感觉wifi soc里用linux的方式开发,可能是一个趋势。
VSF经过了一段时间的开发维护,也加入了linux子系统,并且已经具备一定的兼容性,可以直接编译一些linux的应用,我们也做了一些库的移植,比如libcurl等等。VSF里的linux子系统使用按需开发的方式,毕竟linux系统需要的API太多,实际使用的时候,如果缺什么API,我们会尽量补上。当然,由于芯片没有MMU,所以有一些依赖MMU的API无法实现,比如fork,需要用spawn替代。一些维护了比较好的linux软件,基本都有HAVE_FORK/HAVE_VFORK/HAVE_WORKING_FORK等等的配置,所以可能只是配置一下就行。
举个栗子,使用linux里的curl来实现一些网络相关的功能,或者可以用其他其他基于libcurl的网络应用:
下面上正文了,一些技术的实现方式。
1. 先上一个巨坑:实现linux子系统的话,第一个问题,C库以及c++库。
在linux上,c++库是基于底层的linux提供的各种API实现的,但是在MCU里,编译器会自带一些C库。这里就看编译器自带的C库的retarget能力了,首先点赞的是IAR,自带的C库可以直接使用,通过retarget可以对接到linux子系统里的API,唯一的限制是open的返回fd是int8_t类型的,不是标准的int类型的。newlib必须差评,这个库基本没怎么考虑嵌入式的应用场景,所以很多开源的软件框架(比如xboot),自己做了c库,就是这个原因。VSF也自己实现了C库,可以通过配置来选择是否使用,并且,还可以使能C库API的wrapper,避免和编译器自带的库冲突。
C++库,必须先呵呵。
很多开源软件框架,即使实现了C库,也不一定对接了c++,这里是巨坑。。巨巨坑。。。巨巨巨坑。。。
不过,VSF会尝试解决这些问题,目前在Visual Studio的clang以及arm-none-eabi-g++下,已经可以编译一些C++的代码。不过还有一些静态实例初始化的问题,已经知道解决方法,还好目前用的一些C++应用,还不受这个影响。这里先留个TBD,等后面处理好后,我再补充。
[我就是TBD]
另外,后面还会尝试使用musl,这个是基于posix的C库。
2. linux的进程、线程对接
大部分RTOS下,其实没有进程的概念,都是线程,进程也只是模拟出来的,VSF也是一样。并且,vsf的linux子系统支持很多相关的功能,例如线程本地存储(TLS,pthread_key基于tls)等等。也哟很多相关的API,比如直接使用sytem函数来启动一个进程,执行一个命令,这些都和linux的完全兼容,并且linux的signal机制也支持。
3. 文件系统 fd,网络 socket,v4l2的设备等等
linux下,一些皆文件,所以也需要设计一个相对完善的linux下的fd对接机制,并且支持相关的各个功能,比如select/poll(状态触发,边沿触发,POLLIN/POLLOUT...)等等。socket、named pipe、v4l2等等,都是通过这个fd机制对接的,甚至可执行程序的入口也是这么对接的。
4. 各种常用库,比如getopt、libusb、sdl、libcurl等等
有些库是自己实现,比如libusb,为了节省资源占用,按照libusb的接口完全自己重写了一套。有些是直接使用linux里的代码或者一些其他开源软件,比如getopt、libsdl2和libcurl,一般这类代码的设计的时候,已经考虑了可重入,直接用就行了。
如果要移植一些linux的代码,步骤如下:
1. 在实际linux下编译一下,目的是为了生成一些配置文件
2. 基于Linux下生成的配置文件,做一些修改(一般就是直接编译,然后看是否有报错,比如缺啥API等等,再修改配置文件)
都是一些类似HAVE_FORK,HAVE_STDLIB_H之类的配置
3. 如果在windows下编译的话,编译器会默认定义_WIN32、_MSC_VER之类的,这个可能会使得代码包含一些windows的头文件。需要在相关代码里,#undef _WIN32、#undef _MSC_VER等等
4. linux的很多应用不考虑资源使用,可能会需要修改一部分应用代码。比如,之前移植的一个应用,直接在stack上分配128K内存,这类问题只能修改代码了。
5. XIP模式下,实现动态加载
这个部分挺麻烦,不过并不是所有的软件都会需要修改。linux的应用软件启动后,会加载软件的资源,初始化一些内存等等。但是MCU里,往往没有这个资源做动态加载。VSF通过另外一种方式来实现这个过程(程序还是在flash里,ram重新生成一份示例),git的移植就是必须要支持动态加载,因为git会在内部再次调用git,所以会需要多个git的实例。有这个需求的用户,加群咨询。
6. VSF里的代码补充完整,如果有些API功能不完善,或者缺什么API的话,VSF团队会负责增加维护
已经移植/测试过的一些软件(不完整列表):
1. ncurses
2. git
3. curl
4. less
5. quickjs
6. sdl2
7. wamr
8. xfel
9. openocd
......
AIC8800M开发用户进群后,群公告里有上手说明的连接。
其他用户想玩一下的话,可以用windows下的visual studio工程,推荐最新的Visual Studio 2022。
仓库:
https://github.com/vsf-linux/vsf.linux
https://gitee.com/vsf-linux/vsf.linux
clone所有子仓库后,vsf里也有一些子仓库需要clone,后续会提供repo的管理方式。
注意,如果是用gitee的话,8086tiny仓库不要clone,因为gitee不支持数字开头的仓库。
vsf里需要的子仓库:PLOOC、freetype、libpng、lua、zlib、SDL_image、SDL_mixer、SDL_net、SDL_ttf
直接用project/vc_sdl2来测试。
Visual Studio需要安装:使用C++的桌面开发、通用Windows平台开发、适用于v143生成工具的C++ Clang、适用于Windows的C++ Clang编译器
公开的应用移植,仅仅是用于测试VSF里的Linux子系统的兼容性,没有太多实用价值。
不过,会有一些应用,我们后面会尝试放到嵌入的环境里跑一下,大部分C语言的应用直接可以用,只要嵌入式环境的性能和资源足够。
一些c++的代码,等我们对接了g++的库之后,也应该是直接可以用的,不过可能会针对实际的嵌入式环境,做一些优化。
DUNGEON_RUSH: