之前尝试的linux开发方式,基本也有一定成熟度了,参考链接
目前主推的开发方式,已经完全兼容linux的玩法了,并且可以合法使用GPL的软件
包管理器,各种原版软件(busybox、curl等等)
直接使用手机控制和配置
惯例先秀一下开发板
由于芯片的SDK并不是公开的,如果需要编译固件的话,需要公司名字,然后和芯片原厂签NDA,拿到SDK后,加入代码仓库,可以编译固件。
没有SDK的话,可以编译成动态加载的可执行程序,打包后可以使用包管理器安装。
可以通过"echo COMMAND >> /root/.profile"加入到启动脚本里。
支持webterminal,可以通过网页来用命令行配置管理,支持linux/windows/macos/android/ios/鸿蒙
支持原版busybox,虽然并不推荐,因为会占用较多的ram
使用vi编辑/root/.profile启动脚本
应用开发方式视频,GPL开源协议的代码,必须编译打包为软件包,这样内核代码可以不受GPL协议传染。
最近尝试了一下wifi/bt soc上,动态加载用户应用的方式。又学到很多没用的知识。
0. 基本需求
0) 应用需要方便编译,使用比较通用的格式
elf:还有谁?
1) 应用代码部分最好不占用ram,XIP方式运行
elf: 呃呃呃,你再说一遍?
2) 用户开发简单,和普通的c一样,甚至可以用其他语言,rust、go等等,反正能编译成elf就行
elf:
3) 支持cortex-m等MCU芯片
cortex-m: 纳尼
4) 全兼容,基于新版本编译的同样代码,可以在旧版中使用,反过来也一样
1. elf动态加载、地址无关、cortex-m
0) gcc编译器使用-fPIC,产生的是got-based position independency。
科普:GOT,Global Offset Table,说白了就是一个存放变量和函数的地址数组,在ram中,用户可以在GOT里实现重定位
优点:随便乱来,反正地址都是loader决定
缺点:arm-none-eabi-gcc有BUG,产生基于R9寄存器的GOT代码的时候,PLT(不用明白,反正就是一些代码,用于调用一些内/外部函数等等)里的代码访问GOT还是用PC+偏移,不是用R9寄存器。并且,已知这个BUG好几年前就有,ARM也不会去修复这个BUG。
1) clang/iar编译器使用-fropi -frwpi,mdk估计也是这个,产生的是embedded position independency。
优点: 简单,R9只是指向data/bss/noinit的整块内存,不需要重定向
缺点: 由于没有重定向,所以无法访问外部函数,因为没有从定向操作,也不能对外提供API
workaround: VSF黑科技,自己实现PLT(支持动态库)
2. 最终方案
0) 使用clang编译器编译elf,ARM今后主力支持这个,反正也免费
1) VSF host程序下的配置:
VSF_USE_LOADER 使能加载器
VSF_LOADER_USE_ELF 支持elf加载器
VSF_LINUX_USE_APPLET linux子系统,支持applet(高大上的说法,其实就只是编译出来的elf)
VSF_LINUX_APPLET_USE_XXXX linux下哪些头文件支持在applet里使用
2) VSF applet下的配置
直接用vsf.linux仓库下,applet/vsf_usr_cfg.h: https://gitee.com/vsf-linux/vsf.linux/blob/main/applet/vsf_usr_cfg.h
3) applet应用开发
头文件(包括C库头文件,位于simple_libc下): https://gitee.com/vsfteam/vsf/tree/master/source/shell/sys/linux/include
直接使用linux的方式开发,如果再linux下可以用,按照applet目录下的编译命令,编译后就可以在vsf里使用。
使用方法,下载到AIC8800M的内部flash中,然后,vsf的linux里,运行loaderelf 0xXXXXXXXX(flash中的地址)。
上图:
vsf 说:quickjs + MEUI -- 使用react或者preact开发UI应用
https://whycan.com/files/members/3294/meui.png话说这种用js开发的应用,怎么保证代码的安全性呢?
脚本开发的话,估计很难保证代码的安全性,即使使用quickjs的bytecode的话,也都是公开的。
js一般也只是用于对接前端的UI开发,不过这个也就只是在PC上玩玩,MCU里的资源和性能不够玩这套
vsf还是走自己的应用路线吧,移植linux应用想扩大生态是徒劳的。我能在linux上跑,为什么还需要vsf呢?
这个就是VSF的路线,如果你都直接用linux了,那没必要上VSF,多此一举。
VSF里用linux的应用代码,目前已经有几个项目在出货了,这个是因为项目需求才做的(客户给钱了,我们就开发),只是现在才开始推而已。其实,早在几年前就做了这个,在我们自己的项目里用的,之后还移植到ESP32里:https://whycan.com/t_5718.html
一般是在wifi soc上用的,这些芯片里,跑原版linux代价太大,而且都不一定可以跑得动的。
wifi soc里的使用,参考这里:https://whycan.com/t_8363.html
libuvc是基于libusb的USB UVC(USB Video Class)驱动,VSF系统具备完善的fd事件机制(libuvc需要),也支持相对完整的libusb库。所以移植libuvc相对而言,应该会比较简单。
VSF以及linux子系统,参考:https://whycan.com/t_8363.html
按照移植步骤的话,第一步是在linux下编译libuvc,使用自动生成的libuvc_config.h:
<code>
#ifndef LIBUVC_CONFIG_H
#define LIBUVC_CONFIG_H
#define LIBUVC_VERSION_MAJOR 0
#define LIBUVC_VERSION_MINOR 0
#define LIBUVC_VERSION_PATCH 6
#define LIBUVC_VERSION_STR "0.0.6"
#define LIBUVC_VERSION_INT \
((0 << 16) | \
(0 << 8) | \
(6))
/** @brief Test whether libuvc is new enough
* This macro evaluates true if and only if the current version is
* at least as new as the version specified.
*/
#define LIBUVC_VERSION_GTE(major, minor, patch) \
(LIBUVC_VERSION_INT >= (((major) << 16) | ((minor) << 8) | (patch)))
/* #undef LIBUVC_HAS_JPEG */
#endif // !def(LIBUVC_CONFIG_H)
</code>
第二部,建立visual studio测试工程,从vsf.linux/project/vc拷贝一份到vc_libuvc。
在工程里,加入libuvc的源码:
加入包含路径:
其中,libuvc\raw是libuvc目录。libuvc\port是libuvc的移植目录,里面存放linux下编译libuvc时自动生成的libuvc_config.h(按照linux下编译libuvc生成的目录结构)。
宏配置,使能APP_USE_LIBUVC_DEMO:
libuvc的main入口修改:
linux fhs里,安装libuvc demo(在vsf_main.c中的vsf_linux_create_fhs函数):
这里就是绑定uvc可执行文件为uvc_main(之前的libuvc example的入口)。
第三部,编译
提示错误:
1. frame-mjpeg.c里,jpeglib.h头文件没找到。
不支持mjpeg,frame_mjpeg.c不参与编译。
2. 一些库函数冲突,看了一下,是因为包含了windows的头文件,在libuvc_config.h中加入如下内容:
第四部,资源优化
既然在windows上移植,暂时不需要优化,先跑通功能。
第五步,动态加载
暂不考虑,先跑通功能。
额外的异步,windows下的winusb驱动,需要定义具体设备ID,修改vsf_usr_cfg_win.h:
这里使用的UVC摄像头的PID/VID就是04F2/B130。
windows上,需要用zadig为这个摄像头安装winusb驱动。
摄像头接入PC后,编译运行:
这里的提示,就是UVC摄像头已经识别,使用了libusb的驱动。
运行demo(命令行输入uvc,按回车):
UVC识别OK,不过后面有运行错误,IO Error,libuvc开源的,所以可以简单调试一下。
调试发现,是如下位置出错:
上USB协议分析仪,截取报文:
看错误,是UVC摄像头的问题,几个UVC的标准请求没有响应。
等新的UVC摄像头,到了之后再测试。
本帖是系列贴,先是简单介绍一下,之后会有一些好玩的应用发布,不过基本也都只是基于我们的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等等的配置,所以可能只是配置一下就行。
如果买了AIC8800M开发板的用户,淘宝里有群号直接加群就行。
有兴趣的话,可以加群:736714326(注明AIC8800M,或者算一道题),手动屏蔽,不知道本论坛是否可以放联系方式
举个栗子,使用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:
sdlpal:
git:
xfel & openocd:
购买地址:
https://item.taobao.com/item.htm?id=676758017780
https://item.taobao.com/item.htm?id=676868663805
whycan首发,可以随意转载,只需注明出自VSFteam即可。
2020年底,在esp32s2上尝试过,帖子在这里: https://whycan.com/t_5718.html
不过,idf的环境,加入的文件过多的话,链接阶段会有错误,给官方提了issue也是年半之后才答复( https://github.com/espressif/esp-idf/issues/6061 ),半年后项目都黄了。
现在换了另外一个wifi芯片,整套系统基本跑起来了,linux的核心的话,需要在源系统的基础上,增加20-30KB的代码占用(CortexM4)。对于上M字节的wifi芯片,貌似只是小水水。
而且,开发的时候,可以直接使用Visual Studio(支持x86和x64),开发调试完成后,再放到MCU环境里编译。
秀一些操作:
1. curl测试REST API
2. git clone
3. telnetd
VSF已经支持了AIC8800,并且正在逐步完善各个外设驱动。已经拿到开发板的童鞋,可以先看一下下面的步骤。
零、芯片简介
1. 240M CortexM4F内核,2M字节flash,992K字节sram
2. 双频WIFI6,286.8Mbps@TX,229.4Mbps@RX
3. 双模BT5
4. 硬件加速引擎,AES/RSA/HASH/ECC
5. USB 2.0 OTG内置高速PHY
6. 内置PMU
7. 5x5 QFN48
8. UART/SPI/I2C/SDIO etc
9. 各种未公开特性,欢迎来撩
一、准备
软件:
1. 编译器,以及开发相关的工具
WIndows下:IAR EWARM 8.40 或者 arm-none-eabi-gcc + cmake + ninja + openocd + vscode
Linux下:arm-none-eabi-gcc, cmake, ninja, openocd, vscode
2. 串口中断,需要支持xmodem发送固件
3. git工具,比如wingit + tortoise git
4. 调试相关的软件,比如openocd。如果使用jlink/dap等IDE已经支持的调试器的话,则不需要额外调试软件。
硬件工具:
1. AIC8800M开发板
2. USB转串口
3. jlink或者cmsis-dap等SWD调试工具
二、下载VSF
可以下载vsf,更新submodule。也可以直接下载vsf-all-in-one。下载好的一些第三方代码,需要打补丁。
1) 使用GIT工具下载VSF,并且更新submodule:
https://github.com/vsfteam/vsf.git
https://gitee.com/vsfos/vsf.git
目前的工程,需要如下子模块(也可以下载所有子模块):
1. source/hal/driver/AIC/AIC8800/vendor
2. source/utilities/compiler/arm/3rd-party/CMSIS
3. source/utilities/3rd-party/PLOOC/raw
4. source/component/3rd-party/mbedtls/raw
5. source/component/3rd-party/btstack/raw
6. source/component/3rd-party/lvgl/raw/lvgl
7. source/component/3rd-party/freetype/raw
8. source/component/3rd-party/zlib/raw
9. source/component/3rd-party/libjpeg-turbo/raw
10. source/component/3rd-party/libpng/raw
11. source/component/3rd-party/coremark/raw
12. source/component/3rd-party/evm/raw
13. source/component/3rd-party/lua/raw
14. source/shell/media/sdl2/3rd-party/SDL_image
15. source/shell/media/sdl2/3rd-party/SDL_ttf
16. source/component/3rd-party/lvgl/extension/lv_lib_freetype/raw
2) 使用GIT工具直接下载vsf_all_in_one
https://github.com/vsfteam/vsf-all-in-one.git
3) 开发IDE支持
1. IAR
复制IAR的AIC8800 flashloader:
把source/hal/driver/AIC/AIC8800/vendor/ide/iar下的AICSemi目录复制到IAR安装目录下的arm/config/flashloader目录下。
2. MDK
3. VSCode
4) 第三方代码补丁
1. IAR
vsf\example\template\project\iar\vsf_template.eww
Workspace里,选择“vsf_template_aic8800”。
在工程中,修改zlib源码,文件vsf\component\3rd-party\zlib\raw\inftrees.c,inflate_table函数:
``` c
int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
codetype type;
unsigned short FAR *lens;
unsigned codes;
code FAR * FAR *table;
unsigned FAR *bits;
unsigned short FAR *work;
{
```
改为
``` c
int ZLIB_INTERNAL inflate_table (codetype type, unsigned short FAR *lens,
unsigned codes, code FAR * FAR *table,
unsigned FAR *bits, unsigned short FAR *work)
{
```
然后就可以编译了。
2. GCC
不需要修改
三、开发板硬件说明
1) 基本说明
AIC8800M开发板上,引出了所有的芯片IO和电源。引出了调试串口引脚和SWD调试引脚。由于芯片么有复位引脚,所以做了电源复位按键PRST,按下后,切断电源,释放后恢复。AIC8800启动是通过PWR_KEY引脚上拉实现的,可以通过开发板上的PWR按键来启动AIC8800M。
2) 硬件初始化
第一次使用AIC8800M的时候,芯片的USR flash并未初始化,所以需要通过串口命令来进行芯片的初始化,串口设置为921600_8N1。
启动的时候,串口上会提示boot abort: -1,表示AIC8800的USR flash没初始化。这个时候,执行如下2条命令(按键输入命令,然后按回车):
f 1 3 1 2 1
f 3
执行完成后,重新上电(按一下PRST按键)。这个时候会提示boot abort: -7,表示flash中没有可以启动的应用镜像。
如果芯片里已经下载过可以使用的程序的话,串口上会提示ready to boot...,并且进入应用程序。注意,进入应用程序后,不能通过SWD接口调试,比如在boot模式才能调试。如果已经下载了程序,可以在上电的时候,疯狂按回车,终止跳转到应用程序,停留在boot模式下(提示符Boot >)。
3) 下载程序
可以通过串口下载程序,在boot模式下,执行下面的命令
x 8000000
然后,通过xmodem(1K)发送程序镜像。
4) SWD调试
在boot模式下,可以通过SWD下载程序,并且启动调试。
在跳转到应用后,只能通过SWD以attach的方式来调试。
1. IAR
如果之前已经复制好AIC8800的flashloader的话,可以直接通过SWD调试器来调试。注意如果需要选择芯片的arch的话,这里必须选择Cortex-M4.
2. GCC
TODO
Happy Hacking!!!
1. BaseObj.c 39行,需要加类型转换
Error[Pe167]: argument of type "NewFun" is incompatible with parameter of type "void *" Z:\vsf\example\template\demo\pikascript\pikascript-core\BaseObj.c 39
2. PikaOjb.c 298和473行,同样类型转换
Error[Pe167]: argument of type "NewFun" is incompatible with parameter of type "void *" Z:\vsf\example\template\demo\pikascript\pikascript-core\PikaObj.c 298
Error[Pe167]: argument of type "Method" is incompatible with parameter of type "void *" Z:\vsf\example\template\demo\pikascript\pikascript-core\PikaObj.c 473
IAR里运行U盘里的py脚本,不过IAR编译有几个错误,在这里: https://whycan.com/t_7587.html
已经提交,工程位于source/example/template/project/cmake/esp32s2下
编译的话,需要定义一个全局的环境变量VSF_PATH,设置为clone的vsf的目录
然后,使用esp的方式直接编译即可。
如果编译过程总,提供btstack文件找不到的话,做如下修改:
1. main/CMakeLists.txt中,去掉btstack的.c,以及去掉btstack_demo.c
2. source/example/template/config/vsf_usr_cfg/vsf_usr_cfg_esp32s2.h里,APP_USE_BTSTACK_DEMO配置为DISABLED
esp32的windows环境下,遇到一些问题,就是如果参与编译的文件太多,连接会出错,官方没有提供任何解决方案。
linux环境下没问题。
解决方法,去掉一些模块,修改source/vsf/component/CMakeLists.txt,去掉3rd-parth、crypto、debugger、tcpip、ui。当然,实际可能不需要去掉这么多
是的,更新会提交到这里,不过,目前还没更新。之前的更新只是内核的移植,USB移植并不完整
楼主牛逼,建议给官方提PR...
SDK暂时没有host驱动,但是从这里发布的进度来看似乎是有这个计划的:https://esp32.com/viewtopic.php?f=10&t=14532
原厂估计不会理我吧。。。。
后面几个wifi芯片,我们都会玩玩,同样的平台,同样的开发方式
esp32s2的估计这周提交,前两天优化了设备插拔的部分。