最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Sega 32X上的Linux。谁还需要硬件同步原语呢?
时间:2026-07-15 19:36:06 编辑:袖梨 来源:一聚教程网

我在固件/操作系统/嵌入式领域已经工作了2年多(从专业角度来说),当你试图找到新工作时,经常看到的一个要求是"能够从头开始处理板卡启动"。
我知道这听起来不太有趣,但对我来说,除了找工作(这反正不是我的主业)之外,让一块硅片运行你制作/帮助制作的东西是非常有趣的。你可以尝试许多构成结果的不同层次:模拟器、技术文档、实验、调查……你知道的;就是那些常规的工程工作。
并不是说阅读90年代初扫描的数据手册是我的爱好(有些文档是直接嵌入PDF的纯图像),但其中有些东西让我每次都忍不住回来查看。
我实际上是在2013/2014年开始做这个的。那时我12/13岁,我清楚地记得父母给我买了第一部手机。那是一部基于联发科6589四核处理器的手机,配备1GB内存。很强大的配置吧!
当时(没过多久),谷歌发布了Android 5.0 Lollipop;但手机厂商决定不将手机更新到该版本。我真的很失望……所以我不得不亲自动手。
我会稍微总结一下这个故事,因为它有点长,但要点是:我要求公司遵守GPL并发布该手机的Linux内核源代码;他们对此表示反对,但作为社区我们团结起来,他们最终发布了源代码(连同其他一些手机的代码树)。
当我看到源代码质量低劣,且板级配置无法在手机上启动时,我感到很惊讶。幸运的是,当时我找到了一个MediaTek ALPS完整源码的泄露版本,该版本针对6589的一个变种,看起来很有希望(包含完整的Little-Kernel引导程序、基带、预引导程序、Linux内核和AOSP),于是我进行了检查。
我花了几个月的时间试图逆向工程手机厂商提供的原厂启动镜像中捆绑的zImage的部分内容,以填充联发科代码的部分内容(主要涉及LCM、电池、芯片组特性等),经过大量深入挖掘和实验(以及与xda-developers论坛上的酷友们进行的良好交流)后,我成功在手机上运行了Android 5.0;请注意,这并不完美。没有蓝牙,没有HWComposer(硬件加速),没有媒体引擎……但看到纯净、未被篡改的全新Material Design出现在我的手机上时,我感到震撼不已。
Android 5.0 Lollipop
我应该 probably 试着把这个故事单独发一篇帖子... 某天。
强大的世嘉32X
于1994年11月在北美/欧洲发布(日本为1994年12月);世嘉32X是一款附加设备,承诺作为16位时代Genesis与即将推出的32位世嘉土星之间的过渡步骤。我不是一个好作家,所以导致那个特定时刻的故事(对于世嘉来说)有些动荡(世嘉日本vs世嘉美国),所以我将把它留给读者作为任务。
无论如何,在32X之前,SEGA推出了一款CD附加设备;Sega CD(或者如果你是欧洲/日本用户的话,叫Mega CD)。它插在Genesis的扩展槽上,能够实现CD质量的音频流(以及游戏/游戏资源流)。它本身是一敏感公共事务表述立的机器(与Genesis相比,它拥有更高频率的68000处理器)。有2个独立的型号,第一"代",是前置装载式的...:
世嘉[Mega]CD Model 1 搭配 Mega Drive/Genesis Model 1
...第二个,顶部装载的:
世嘉[Mega]CD Model 2 搭载 Mega Drive/Genesis Model 2
但这篇文章是关于32X的...所以 here it is:
实际的addon被插入到Genesis的卡带插槽中(它有一个独立的电源适配器和视频输出,后者的视频输出时序/视频/颜色通道信号后来被"合并"到Genesis的视频输出上)。
Sega 32X & Genesis Model 2
如果你曾经有幸搭建过Power Tower,你会知道拥有3个独立的电源砖,加上从32X获得立体声输出的电缆、"补丁"电缆以及我现在可能忘记的许多缺失的小部件,绝不是什么简单的事。
但是什么赋予了所有这些力量?
32X硬件规格
诚然,这个插件比基础控制台功能强大得多:
正如你所见,差异 quite 大。我甚至没有列出所有的差异,但主要的我能想到的就是这些。
对SEGA来说不幸的是,其发布几乎与索尼PlayStation 1同时进行;后者凭借更简单的架构准备颠覆游戏行业。此外,SEGA土星也接近发布日期(因此消费者在选择哪款产品时感到困惑)。这完全是SEGA一贯的风格!
无论如何,如果我们在Jaguar上运行了Linux,我们应该能够对32X做类似的事情;对吧?
jmp _linux, the rendezvouz
让Linux在SH2上运行(运行是指,通过UART打印任何有意义的内容)需要一些头脑风暴。
我们需要设置3个不同的CPU,2个SH2和1个68000。幸运的是,GitHub上有现成的例子,所以我选择了看起来最受欢迎的32X Hello World示例:Chilly Willy's Sega MD/CD/32X devkit。
基本示例通过特定的内存映射IO地址在32X(s)和68000之间建立通信通道(这样你就可以让68000做一些32X无法完成的工作);准备SH2s(设置缓存,直接从68000机器代码上传来自卡带的SH2代码...)并使主SH2跳转到它;而次级SH2则被停放。
我所做的就是扩展这个功能,以便我可以有一个简单的状态机,将字符推送到Genesis的UART上(因为32X没有直接访问权限);但是有一个问题...
将Linux移植到一个新的(而且是相对较新的,从发布时机来看)平台时,最大的障碍主要是进行布线以使其启动和运行;如果你有足够的内存来加载它,通常就是这种情况。对我们来说不是这样...
幸运的是,有基于FPGA的闪存卡带适用于该游戏机(使您能够运行基础型号和32X的游戏;甚至还有专门的"核心"提供Sega CD支持,如果您没有该附加设备的话!)。其中一个(系列)卡带来自Krikkz。
他基本上做了flashcarts所做的事情,但在几乎所有方面都更进一步,这不仅仅是关于运行游戏!
我们对这些购物车的某个特殊部分很感兴趣:
扩展SSFv2映射器
基于卡带的旧系统通常有这种关于"映射器"的概念。
映射器基本上是位于卡带上的集成电路,它们增强了游戏机在内存处理能力方面的功能。
它们还可以提供与内存无关的其他功能,例如世嘉的Virtua处理器(SVP),它有一个三星设计的DSP来执行繁重的数学计算(使Virtua Racer能够在基础Genesis上显示其所有3D多边形效果);或者任天堂的SuperFX芯片;它提供了与SVP类似的功能,由《雷霆万钧》或《猛禽:猎食者》的创作者Argonaut Games制造。
通常映射器被用于以金融机构切换的方式为更大/更详细的游戏启用更多ROM空间。你会写入某个内存地址/执行特定的访问集,IC会在内部将"扩展"ROM的部分重新映射到控制台可以直接寻址的内存窗口。如果你想想的话,这有点像MS-DOS的HIMEM.SYS的精神。
所以Krikkz基本上为我们完成了所有工作,原来我们可以将ROM作为RAM使用(通过安排某些配置位使ROM变得"可写")。这样我们就能获得4MB的RAM。
我基本上必须扩展SDK示例来完成ROM->RAM映射,但必须为Linux + initramfs二进制文件留出一些空间(基本上是在卡带内存窗口内的实际ROM)。我最终找到了一个ROM 540~KB和其余RAM的 sweet spot。Linux加载器基本上将二进制文件复制到它链接时的内存位置并跳转到那里。
编译和运行Linux
所以,我制作了一个sh2eb-elf交叉编译器并开始编译Linux...但编译很快就失败了。
在我遇到的所有工具链问题中,这个问题可能是最有趣的。
由于某种原因,GCC在编译kernel/nstree.c时出现了ICE(内部编译器错误)。我找到了一个解决方法(当时没有时间提交错误报告)。
在完成所有这些工作后(并编写了一个小型的earlycon驱动程序,以便将一些UART输出从32X传输到Genesis),我得到了最早的Linux消息。
曾经出现过一个独立的问题,某个时刻Linux似乎停止了启动过程并且无限期挂起。
然后我发现了另一组问题,这次是关于:ashlsi3、ashrsi3 和 lshrsi3。我不太确定这些是如何编写的(它们是从 libgcc 的对应部分复制/借鉴的,还是类似的东西?),但比较交叉编译器对这些操作的处理和 Linux 的处理,很明显我们破坏了一个不应该破坏的寄存器。我发现这个问题是因为我开始注意到一些 pr_info() 和 pr_notice() 的栈被破坏了(并且从未返回到调用者),并能够追踪到这里。
然后我为arch/sh/lib/checksum.S做了额外的(类似的)修复,以确保安全;我基本上对shrd进行了门控,因为它在32X中的SH2上不存在(如果使用的话...非法操作码)。
这基本上让我们完成了整个启动过程,直到时钟校准之前;为此我决定为SH2(s) FRT(自由运行定时器)制作一个简单的驱动程序;这也让我们更进一步,我们即将启动init进程。
幸运的是,这次我能够利用ELF FDPIC支持(与Jaguar的FLAT二进制支持相比,这让我更容易)来构建我的rootfs。我也得到了musl-cross-make的帮助;它为我提供了一个sh2eb-linux-muslfdpic-工具链,我可以使用它(我必须说,我在crosstool-ng、buildroot和其他几个工具上奋战了很久,但没有成功)。
所以有了这个,一切都启动了。
案件...结案...?
是的,我忍不住。
事实证明,你需要一些硬件原语来实现CPU间的同步...而32X上的SH2没有这些硬件原语¹。
¹: TAS.B 操作码似乎在 D32XR 等项目中仍在使用,即使开发者手册已要求不要这样做,因为适配器总线没有锁定的读-修改-写周期机制。
我们也没有缓存一致性,所以这是另一个要添加到我们问题清单中的问题。
但是我想,嘿,两个SH2在功能上都是平等的;我们肯定能想出什么办法……对吧?
事实证明,sparc32恰好有一些代码来协助完成这项工作。
我们基本上可以利用Peterson算法来完全在软件中实现所需的原语。请注意,这并不是高性能的,但确实有效。
我基本上必须为所有需要关注的原语(例如 cmpxchg)进行引导,按照 Peterson 所描述的想法。
我还需编写68000的代码(目前仅处理UART相关事务),以协助向两个SH2发送IPI(我扩展了68000可接收的命令,使其能正确执行其任务),并设置共享内存区域以协助同步任务。此时可将68000视为总线仲裁器/额外中断路由器。
从SH2s我刚刚发送了一个"IPI"命令,68000解析该命令并根据数据字中的一个位来决定断言哪个中断线(0为主中断,1为次中断)。
然后是缓存一致性问题,我通过不使用缓存映射(而且,无论如何缓存都是禁用的)来放置Peterson的flag和turn变量(你知道,为了避免SH2在flag的过期缓存值上自旋;例如)。
我还遇到了另一个问题,如何识别哪个CPU是哪个CPU(这样Linux就可以正确管理和发出hard_smp_processor_id()):好吧,考虑到我无论如何都在做软浮点运算;我只是让CPUID_REG指向SH2私有的硬件除法器寄存器(DVSR),这个寄存器没有其他用途,所以它实际上成为了我的"我是哪个CPU"寄存器。这个寄存器在启动时由Linux加载器为primary和secondary SH2s都写入。
性能糟糕,总线争用问题严重;但它确实能工作,这对我来说就足够了。
我必须承认,这并不像那样简单,它真的涉及了大量的调整和( mostly )试错(我还花了两个晚上追踪为什么两个 CPU 都会被唤醒但很快就会空闲,结果发现我需要修复 default_idle() 中的一个问题,这个问题导致调度器出现错误并且无法正确继续执行)。
但这很值得。
我刚才基本上制作了一个简单的控制台显示驱动程序(这样你知道,你可以在实际屏幕上看到它的运行效果)...
不用说,所有这些都需要大量的微调(我也一直在遇到内存不足的问题,需要让Linux和Busybox都进行良好的瘦身),但再次强调,这是一次非常有收获的经历。
杂项配置文件,如果有人想尝试的话
Linux源码树(mars_defconfig)
Busybox配置
Init脚本
相关文章
- 适合小学生玩的游戏推荐 2026小学生喜欢玩的游戏合集 07-15
- 日式rpg游戏合集 2026最受欢迎的日式rpg游戏大盘点 07-15
- 濡沫江湖洛阳郊外隐藏宝箱具体位置一览 07-15
- 暗黑破坏神4怎么堆叠减伤 暗黑破坏神4堆减伤攻略 07-15
- tavo角色卡怎么导入 07-15
- 2026年3-6岁儿童益智游戏APP推荐:寓教于乐的优质之选 07-15