go和c现在是我工作中的主力语言。go在很多领域发挥了强大作用,那go适合嵌入式吗?当前并不适合,但go具有控制硬件的能力,虽然有些繁琐。
本帖最终目的是在全志f1c100s/200s或者说是arm9系列芯片直接运行go程序,主要是把go runtime移植到arm9上。本帖主要是受github的开源项目https://github.com/icexin/eggos的启发,此项目已成功将go runtime移植到x86上。开篇先建立环境:
虚拟环境是qemu-system-arm
先在上面跑个gnu汇编热热身。
arm.zip
最近编辑记录 kekemuyu (2022-03-17 15:52:33)
离线
之前研究过一段时间,基本有两种思路,一种是完全模拟linux上的go runtime,还有一种是go编译器增加NOOS之类的编译选项,改编译器最彻底,最通用,但官方不支持。比较遗憾!
离线
还是不喜欢tinygo这种深度魔改型,最好的方式,还是原生go编译器,增加GOARCH GOOS这种选项,只要增加个BAREMETAL或在NOOS,不管叫什么,就超级感兴趣了。就是有点遗憾~!
离线
@xboot
同感,tinygo等于发明了另一种语言,还是跟随官方go比较好。TamaGo就是增加GOARCH GOOS的方案。但是我更倾向eggos的方案,不用修改官方编译器,他是模拟了linux的中断和系统调用。具体原理请参考这篇博文:https://zhuanlan.zhihu.com/p/265806072
离线
eggos本质是模拟各种linux的syscall吗?
离线
eggos本质是模拟各种linux的syscall吗?
应该是这样,没有详细看,你可以看看eggos的源码,由于go runtime自带内存管理和任务调度,干了很多操作系统的活。只要实现很少的系统调用和中断管理就能移植runtime,eggos的架构图:
eggos的kernel目录是他的核心,可以看到代码量很小:
最近编辑记录 kekemuyu (2022-03-21 15:02:07)
离线
另外还可以参考https://git.sr.ht/~eliasnaur/unik/tree,eggos作者就是受这个项目启发做的。两者原理是一样的
离线
eggos这套机制值得研究,首先得用go搞出hello world,在F1C100S平台上,裸奔启动代码不缺,就缺go编译出来的elf,直接搞成bin文件,然后缺什么补什么
离线
就看连接的运行时的大小了,估计小不了,go的库都比较高级,功能强悍,不过tinygo都能在mcu跑,感觉还是绰绰有余的。
离线
比c大个10几倍有怎样,一个程序自带了多线程和gc,基本上是跑了个操作系统了
离线
是的,大一点,无所谓,基本代替操作系统了,毕竟OS的体积也要算上。
离线
多多研究,如果跑出helloworld了,也许我会入坑
离线
对于大家玩的这些芯片,程序体积不是问题,我个人觉得反而特别合适发挥跨界MCU的优点。32MB的rom,ram,心无杂念的跑一个功能强悍的裸奔程序。系统不稳定都难。
离线
go官方的issue中很多人提出希望添加嵌入式支持,官方没答应,理由是硬件太多,工作量巨大,因为官方需要保证go的一致性和稳定性,可以理解,而且go的应用场景重点不在这方面。其实早期go的版本是支持裸机的,goos=tinygo,后来给删除了。
离线
是的,我也期望go官方能支持裸奔,这样go编译器就不要去操心了,只要专心做好runtime就行了,其实我觉得官方觉得工作量巨大,是因为没有抽象出一个统一的runtime接口,少了一个抽象层,我觉得,随着go的发展,这个抽象层是必须的,不但有一定的扩展能力,还能降低系统耦合度,代码可读性,可维护性。当然这个抽象层是否能设计的好,是否影响效率,就看官方的架构水平了。
离线
看了下eggos,里面实现如下syscall,不是全部linux syscall, 这些syscall,绝大部分还是用go写的。
kernelCalls = [...]uintptr{
syscall.SYS_ARCH_PRCTL,
syscall.SYS_MMAP,
syscall.SYS_MUNMAP,
syscall.SYS_CLOCK_GETTIME,
syscall.SYS_RT_SIGPROCMASK,
syscall.SYS_SIGALTSTACK,
syscall.SYS_RT_SIGACTION,
syscall.SYS_GETTID,
syscall.SYS_CLONE,
syscall.SYS_FUTEX,
syscall.SYS_NANOSLEEP,
syscall.SYS_SCHED_YIELD,
syscall.SYS_MADVISE,
syscall.SYS_EXIT_GROUP,
// TODO: real random
unix.SYS_GETRANDOM,
// may removed in the future
syscall.SYS_EPOLL_CREATE1,
syscall.SYS_EPOLL_CTL,
syscall.SYS_EPOLL_WAIT,
syscall.SYS_EPOLL_PWAIT,
syscall.SYS_PIPE2,
SYS_WAIT_IRQ,
SYS_WAIT_SYSCALL,
SYS_FIXED_MMAP,
SYS_EPOLL_NOTIFY,
}
离线
感觉比较好的思路就是用c完整实现一个类linux的各种系统调用。然后直接用go去编译链接
最近编辑记录 xboot (2022-03-23 20:09:18)
离线
go语言裸机最小生成elf工程:
add_20220409-1201.zip
离线