这些是我对潜在的计算机爱好者个人计算机体系结构的注意事项。有人称它为主板Minix。
这大致描述了一种现成的微控制器组件的体系结构,可用于创建一台基本的独立PC,性能接近于旧的286/386DOS风格的PC。
如果我建造这个,几乎肯定会在铁锈完成。我确实希望能很好地指定协议/操作语义,这样您就可以创建一个用Micro/Circuit Python、C/C++、Ada编写的组件,甚至可以创建成嵌入式Linux PC。
我目前正在做其他项目,但我觉得这将是一个有趣的项目,甚至可以写一本关于学习嵌入式系统的书,或者用嵌入式系统学习Rust?
如果您有兴趣参加这样的系统构建/使用课程,或者有兴趣看到这种情况发生,请给我发个消息。
该项目的目标是设计一种类似于PC的体系结构,使学习嵌入式系统的人们可以轻松地构建单个组件。这包括:
这个想法是让系统的每个部分(或组件)都成为独立的微控制器系统。老实说,这就是今天大多数计算机的工作方式,但我们的想法是能够使用几乎任何微控制器,从8051到ARM Cortex-M,再到RISC-V部件,用于PC的任何一部分。在某种程度上,我甚至可以看到人们甚至用FPGA制造PC的部件。
系统应该使用几乎每台设备都支持并且可以原谅的协议。因此,我计划使用SPI进行系统通信。
因此,SPI是一种简单、快速和可靠的协议,但诀窍在于编写SPI控制器要比编写SPI外围设备容易得多。因为我想让编写组件的人的事情变得最简单,所以他们应该是SPI控制器。但这给我们留下了一个问题,如何使带有N个SPI控制器的PC与单个SPI外设一起工作?这就是事情变得奇怪的地方。
每个组件都是一个SPI控制器,SCK、COPI和CIPO引脚连接到一个中央仲裁器。
每个组件也有两个GIO:输出是一个请求行。这向仲裁器发出该组件想要对话的信号。
一个输入,它是一个前进的&34;行。这向组件发出信号以开始与仲裁器对话。
在这个系统中,仲裁器将支持作为许多线路的SPI外设,或者将根据需要处理多路复用SCK/COPI/CIPO引脚。仲裁器将决定它想要与哪个组件交谈,以及交谈多长时间。当组件将其请求线拉低时,仲裁器最终将通过拉组件来确认这一点';组件可以以它认为的任何速度开始计时SPI数据,直到仲裁器支持的最大速度。当组件完成发送/接收数据时,它检查允许行是否仍然较低。如果是,则该消息被仲裁员接受。如果在组件释放请求行之前,允许行被释放得很高,这意味着仲裁器已经挂起了组件,这意味着。
如上所述仲裁总线协议,服务和发现已连接的组件。
我已经描述了上面协议的最低级别-我们将使用一个笨拙的SPI通信。然而,我还没有描述更高的协议层是如何工作的。
所有设备都将通过邮箱系统进行通信。仲裁器将从组件中获取数据,并将其放入内存对象存储中。每个创建的项目都将被分配一个UUID,该UUID将在创建时返回给组件。然后,该UUID可以放在邮箱中给另一个组件,将对数据的访问权限发送给该组件。每个项目都是只读的。
//从组件向仲裁器发送二进制RPC消息//格式可能是二进制,但可能使用替代命令//使用以下REPL格式?/引导时还会为组件分配UUID。该组件的自有地址为//9ea8b6a7-2967-4db8-98b8-d4577548ed04。//数据可以存储到仲裁器存储空间。然后,可以使用UUID作为引用来//引用数据作为设备间存储。数据//以FIFO为基础进行分配,其中//最旧的存储项变为//丢弃。/仲裁器可以根据配置选择限制创建存储项的速率、最大大小或其他//参数。CREATE(//要写入的字节数,对于动态//长度,可以使用COBS之类的东西或当请求//行被取消断言时设置为零13,//数据的有效负载";Hello,world!";,//No UUID(//无UUID)//当请求//行被取消断言13时,//数据的有效负载";Hello,world!";,//No UUID。如果提供,这会将//创建的uuid放入另一个组件的邮箱中无,)//成功时会将以下uuid返回给该组件->;Result<;3b2fd5d1-ae16-46af-afc1-f60241d0a5b6,创建错误//您可以通过引用您知道的另一个组件的邮箱来发送数据。(#//=。邮箱是作为组件地址提供的。邮箱//是可由组件SEND_MAILBOX(//发送3b2fd5d1-ae16-46af-afc1-f60241d0a5b6的数据引用,//目的地址56c3dbda-c762-4107-be58-855dc8e5aa92,)加载的UUID的FIFO队列)//其他设备可以基于FIFO接收消息,并可以查看。大于usize值的消息将//返回错误Some(32),)->;result<;(13,";Hello,world!";),GetError>;//其他设备可以基于FIFO接收消息,并可以查看//和删除堆栈顶部的项目。如果控制器//在接收到所有字节之前结束消息,则仍会//从FIFO中删除该项。这可以用来简单地将项目放到//FIFO.POP_Mailbox的顶部(//您可以提供一些(Usize)作为最大邮件大小,或者//任何邮件大小都不提供)。大于usize值的邮件将//返回错误某些(32),)->;result<;(13,";Hello,world!";),GetError>;//TODO:如何克隆和修改//由于重新分配而无法硬执行的操作?除非我使用某种//绳索结构,否则插入会很糟糕,这可能太复杂了,无法实现。
//使用枚举类型ID注册我们自己/TODO:多次调用此ID时怎么办?REGISTER_TYPE(IO_CONTROLLER,)->;Result<;9ea8b6a7-2967-4db8-98b8-d4577548ed04,获取错误>;//获取我们自己的ID。匹配注册时给定的ID GET_OWN_ID()->;SPIGetError>;//获取仲裁器接口的限制GET_仲裁器_LIMITS()->;{Result<;9ea8b6a7-2967-4db8-98b8-d4577548ed04,_SPEED_Hz:125000,//最低SPI时钟速率是多少?MAX_SPEED_Hz:8_000_000,//最大SPI时钟速率是多少?Exp_polls_per_sec:100,//预计轮询频率是多少?REQUEST_LINE_SHARED:FALSE,//请求线是否开放排出?TOTAL_MEMORY:524288,//512KiB max_files:512,//一次最大有效记录数}//获取消息创建限制GET_CREATE_LIMITS()->;{max_bytes:512,//最大消息可以是512字节max_bytes_per_sec:4096,//运行资源限制Messages_per_Second:10,//运行资源限制}。
TODO:如何注册多个地址/逻辑寻址?例如,对于有鼠标和触摸板的键盘?可以在每条消息中添加发件人字段,但是我要添加路由层吗?
编写一个简单的引导加载器,可以在总线上枚举、获取映像并重新启动?PXII开机风格?需要枚举类型,甚至序列号等,才能将正确的固件加载到正确的位置。
我可以为这些组件创建一个模拟环境,使用no_std库并使用TCP over localhost来模拟SPI目标环境,基本上提供一个I/O库或一个硬件来模拟系统内的每个组件。也许甚至可以将RTIC移植到模拟环境中,或者仅仅使用QEMU,使用Semihost来模拟SPI/GPIO?
只需做一点工作,我还可能让一个仲裁器,甚至只是一个简单的SPI控制器位于PC之外,将一个或多个模拟组件桥接到具有物理组件的共享网络。
这将允许我快速启动多个设备,无论是从组件软件的角度还是从CPU对Anachro-PC架构的支持来看都是如此。
因为nRF52已经有一个内部引脚多路复用器,所以我可以使用nRF52840(大约有36-48个GPIO)来充当物理仲裁器。假设您需要每个组件的以下端号:
这意味着我们可能可以支持5-8台设备?如果请求行是共享的,可能会更多?如果我需要外部QSPI存储器作为存储,可能会更少?然后,您可以将开发板手工连接在一起,这将是乏味的,但不需要我购买新的硬件也是可能的。
缺点是,作为SPI外设,nRF52840仅支持最高速度为8 Mbps。
我可以把nrf52840之类的东西放在PCB上,然后把所有的管脚都拆成8个管脚。这将允许您轻松地为每个外部组件连接线束,甚至可以做一些愚蠢的事情,如在RJ45或其他设备上运行线缆。
我还可以为常见的足迹制作简单的适配器,比如PJRC的Teensy、Adafruit的Feather或Arduino Uno R3格式。这些将是无元件PCB,带有通孔可焊接头,您可以使用杜邦接头,或某种标准的2x4带状电缆。
首先,我可能会从nRF52开始制作所有东西,因为我手头有很多nRF52。将来,我可能会开始添加。
一旦我有了一个可以工作的设计,我就可以用完整的主板组件制作一个巨型PCB。这真的很酷,但也可能真的很贵或很耗时。