版本协议

GPL 3.0

标签

#第六届立创电赛#UEFI Shell 助手

创建时间:1个月前

111 0

视频

描述

<div class="document"> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;">注:* 为必填项</p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"><strong><span style="color:#0093e6;">请在报名阶段填写 ↓</span></strong></p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"> </p> <h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;">* 1、项目功能介绍</h3> <hr class="horizontal-splitline normal-bold-2" /><p><span lang="zh-cn" xml:lang="zh-cn">正常情况下,双机之间共享文件只是小事一桩,但是当我们身处</span> UEFI Shell <span lang="zh-cn" xml:lang="zh-cn">下面的时候,这就会变得非常麻烦。而这样的场景,对于开发</span> UEFI Shell Application<span lang="zh-cn" xml:lang="zh-cn">是非常常见的。通常只能每次编译之后使用</span>U<span lang="zh-cn" xml:lang="zh-cn">盘拷贝</span>EFI <span lang="zh-cn" xml:lang="zh-cn">文件到目标机上再执行。显而易见需要将</span>U<span lang="zh-cn" xml:lang="zh-cn">盘插来插去无法麻烦。之前我的解决方法是购买一个</span> USB<span lang="zh-cn" xml:lang="zh-cn">切换器,这样只用按键即可来回切换节省了插拔的动作。但是这样的方法仍然很麻烦,切换之后</span>U<span lang="zh-cn" xml:lang="zh-cn">盘可能无法识别。最终萌生了写一个辅助设备的想法。</span></p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"> </p> <h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;">*2、项目属性</h3> <hr class="horizontal-splitline normal-bold-2" /><p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"><span style="color:#95a5a6;font-size:14px;">原创项目,首次公开</span></p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"> </p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"> </p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"> </p> <h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;">* 3、开源协议</h3> <hr class="horizontal-splitline normal-bold-2" /><p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"><span style="color:#95a5a6;font-size:14px;">GPL3.0开源协议</span></p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"> </p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"><span style="color:#95a5a6;font-size:14px;">注:利他即利己,请认真阅读下述内容。</span></p> <ol style="line-height:1.8;"><li class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt pap-hanging-indent-1.6em" style="line-height:1.8;"><span style="color:#95a5a6;font-size:14px;">拥抱开源,赋予项目无限价值。建议项目核心功能开源80%以上;</span></li> <li class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt pap-hanging-indent-1.6em" style="line-height:1.8;"><span style="color:#95a5a6;font-size:14px;">若某一部分功能不可替代且删掉之后项目无法解决对应的问题,则这一部分实现的功能就是项目的核心功能;比如设计了一台电子负载且设计了一款上位机软件监控功率变化,则电子负载为核心功能,上位机软件为辅助功能;比如电子负载中使用了一款隔离485模块与上位机通信,则此485模块实现的通讯功能为辅助功能;</span></li> <li class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt pap-hanging-indent-1.6em" style="line-height:1.8;"><span style="color:#95a5a6;font-size:14px;">项目应选择适合自己的<span style="text-decoration:underline;"><a href="/posts/98fdb2accd754af7b51990790db3b47a">开源协议</a></span>,若项目引用其他开源项目,应注明来源并遵循原作者的开源协议规定;原创项目推荐使用GPL3.0开源协议;</span></li> <li class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt pap-hanging-indent-1.6em" style="line-height:1.8;"><span style="color:#95a5a6;font-size:14px;">直接引用开源项目的原电路或原代码实现的功能不可作为自己项目的核心功能、使用市场上通用模块直接实现的功能不可作为自己项目的核心功能。</span></li> </ol><p style="line-height:1.8;"> </p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"><strong><span style="color:#0093e6;">请在竞赛阶段填写 ↓</span></strong></p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"> </p> <h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;">*4、硬件部分</h3> <hr class="horizontal-splitline normal-bold-2" /><p><span lang="zh-cn" xml:lang="zh-cn">最终的方案是:对于运行</span>UEFI Shell<span lang="zh-cn" xml:lang="zh-cn">的目标机,辅助设备将自身模拟为</span>U<span lang="zh-cn" xml:lang="zh-cn">盘,所有的</span> UEFI <span lang="zh-cn" xml:lang="zh-cn">都会支持这样的设备,就不必加载额外的驱动。同时模拟</span>U<span lang="zh-cn" xml:lang="zh-cn">盘上放置一个</span> UEFI Shell <span lang="zh-cn" xml:lang="zh-cn">的程序,这样对于没有内置</span> UEFI Shell <span lang="zh-cn" xml:lang="zh-cn">的目标机也会省去查找制作启动盘之苦。对于</span> UEFI Shell <span lang="zh-cn" xml:lang="zh-cn">的目标机,数据读写也是发生在</span>U<span lang="zh-cn" xml:lang="zh-cn">盘上的。另外一端,使用串口来进行通讯。</span></p> <p><span lang="zh-cn" xml:lang="zh-cn">选择的硬件是</span> ESP32 S2<span lang="zh-cn" xml:lang="zh-cn">,因为这款模块速度足够快,内存也挺大,支持</span> USB Device<span lang="zh-cn" xml:lang="zh-cn">,同时自带了</span>2MB <span lang="zh-cn" xml:lang="zh-cn">的</span>pSRAM<span lang="zh-cn" xml:lang="zh-cn">,这样我们可以将需要交换的数据放置在</span>pSRAM <span lang="zh-cn" xml:lang="zh-cn">上。串口芯片选择了</span> CH340B<span lang="zh-cn" xml:lang="zh-cn">,价格适中,最高波特率</span> 2,000,000<span lang="zh-cn" xml:lang="zh-cn">。同时</span>B <span lang="zh-cn" xml:lang="zh-cn">这个后缀的</span> CH340<span lang="zh-cn" xml:lang="zh-cn">内置了</span> eePROM <span lang="zh-cn" xml:lang="zh-cn">可以写入自定义的数据,这样方便我们直接编写自动识别串口的</span>Windows<span lang="zh-cn" xml:lang="zh-cn">端代码。</span></p> <p> </p> <p> </p> <p><span lang="zh-cn" xml:lang="zh-cn">为了达成目标,首先开始硬件电路的设计。</span></p> <p>1.ESP32-S2 <span lang="zh-cn" xml:lang="zh-cn">最小电路部分如下,</span>3.3V<span lang="zh-cn" xml:lang="zh-cn">供电,预留</span>GPIO0 <span lang="zh-cn" xml:lang="zh-cn">和</span>EN <span lang="zh-cn" xml:lang="zh-cn">两个按键用于下载(自动下载,一些特别情况才需要手工触发下载)。</span></p> <p> </p> <p><span lang="zh-cn" xml:lang="zh-cn"><img src="//image.lceda.cn/pullimage/gM60uuOQRMsft4khFwte3xww4nGRB2g5e0lh4dd7.png" alt="" /></span></p> <p>2<span lang="zh-cn" xml:lang="zh-cn">.</span> ASM1117 5V <span lang="zh-cn" xml:lang="zh-cn">转</span>3.3V <span lang="zh-cn" xml:lang="zh-cn">供电。</span></p> <p><span lang="zh-cn" xml:lang="zh-cn"><img src="//image.lceda.cn/pullimage/WVzlF0qs6uyHj6gKFEXWjSwCcAMBsAv4EBZzJgzS.png" alt="" width="1146" height="673" /></span></p> <p>3.CH340B USB<span lang="zh-cn" xml:lang="zh-cn">转串口,提供程序下载和</span>Windows<span lang="zh-cn" xml:lang="zh-cn">通讯功能。其中的</span>LED2 <span lang="zh-cn" xml:lang="zh-cn">是</span>CH340B <span lang="zh-cn" xml:lang="zh-cn">提供的状态灯,当有发送时,这个</span>LED<span lang="zh-cn" xml:lang="zh-cn">会亮。</span></p> <p><span lang="zh-cn" xml:lang="zh-cn"><img src="//image.lceda.cn/pullimage/XlL3C0zhydcyLa8UEBKLN8NcBrUNEziP1lxxtNrS.png" alt="" width="1179" height="455" /></span></p> <p>4.<span lang="zh-cn" xml:lang="zh-cn">下面的电路配合</span> CH340 <span lang="zh-cn" xml:lang="zh-cn">转出来的</span> DTR<span lang="zh-cn" xml:lang="zh-cn">和</span> RTS <span lang="zh-cn" xml:lang="zh-cn">实现自动下载的功能。</span></p> <p><span lang="zh-cn" xml:lang="zh-cn"><img src="//image.lceda.cn/pullimage/gQ286C218hi1uWnefBY0dyFB1s1GqxkQpN6STPB8.png" alt="" /></span></p> <p>5.<span lang="zh-cn" xml:lang="zh-cn">这是</span>U<span lang="zh-cn" xml:lang="zh-cn">盘端口的</span>USB-B <span lang="zh-cn" xml:lang="zh-cn">型母头接口。这里预留一个跳线,正常使用时,上面没有跳线,被测机和工作机</span>5V <span lang="zh-cn" xml:lang="zh-cn">是分开的,这是为了避免两者</span>5V <span lang="zh-cn" xml:lang="zh-cn">电压不同电流倒灌的情况。如果你想将这个设备当作启动</span> UEFI Shell<span lang="zh-cn" xml:lang="zh-cn">的</span>U<span lang="zh-cn" xml:lang="zh-cn">盘,可以将这里安装跳线。</span></p> <p><span lang="zh-cn" xml:lang="zh-cn"><img src="//image.lceda.cn/pullimage/jUm7DXCdudvSeTucYs9olK7ozWtfsQDhO0BIK4kR.png" alt="" width="587" height="389" /></span></p> <p>6.<span lang="zh-cn" xml:lang="zh-cn">最后是一个预留,用于</span> Debug <span lang="zh-cn" xml:lang="zh-cn">的串口。</span></p> <p><span lang="zh-cn" xml:lang="zh-cn"><img src="//image.lceda.cn/pullimage/3Vw2OGQKymQLfZ4KhFFojlVcfy9gljlnYeD3Zk08.png" alt="" width="1200" height="552" /></span></p> <p><span lang="zh-cn" xml:lang="zh-cn">最终</span> PCB <span lang="zh-cn" xml:lang="zh-cn">设计如下:</span></p> <p> <img src="//image.lceda.cn/pullimage/WtAPfB2b1obZfBrcKPRu4AUoYjKpfEjhxEfheFMd.png" alt="" width="494" height="740" /></p> <p>3D <span lang="zh-cn" xml:lang="zh-cn">预览如下:</span></p> <p> <img src="//image.lceda.cn/pullimage/7g0iVFmSMA97r49StK8BPNpU9r9ipJHKGEyLqmza.png" alt="" width="650" height="821" /></p> <h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;">*5、软件部分</h3> <hr class="horizontal-splitline normal-bold-2" /><p><span lang="zh-cn" xml:lang="zh-cn">接下来就是软件设计了。</span></p> <p><span lang="zh-cn" xml:lang="zh-cn">首先,介绍一下连接被测机的</span>U<span lang="zh-cn" xml:lang="zh-cn">盘代码的设计。这里包含了</span>2<span lang="zh-cn" xml:lang="zh-cn">部分的功能,一个是模拟</span>U<span lang="zh-cn" xml:lang="zh-cn">盘,另外一个是和</span>pSRAM <span lang="zh-cn" xml:lang="zh-cn">的交互。</span></p> <p>1.      <span lang="zh-cn" xml:lang="zh-cn">模拟</span>U<span lang="zh-cn" xml:lang="zh-cn">盘。为了实现这个功能,首先制作一个磁盘镜像。具体方法是在</span> Disk Management <span lang="zh-cn" xml:lang="zh-cn">中使用</span> Create VHD <span lang="zh-cn" xml:lang="zh-cn">功能创建一个虚拟硬盘。</span></p> <p><img src="//image.lceda.cn/pullimage/C3H6kuyKtvfFngNYrSbEm2a6AwVtvQNDUV8JjmuP.png" alt="" width="417" height="420" /></p> <p> </p> <p>        Create VHD</p> <p> </p> <p><img src="//image.lceda.cn/pullimage/Yqi3wo9VxgDUJEif84i5eqQufobBaITskGghwkWg.png" alt="" width="480" height="589" /></p> <p>   <span lang="zh-cn" xml:lang="zh-cn">设定</span> 32MB <span lang="zh-cn" xml:lang="zh-cn">大小</span></p> <p><span lang="zh-cn" xml:lang="zh-cn">上述操作完成后,系统中就出现了一个</span> 32MB <span lang="zh-cn" xml:lang="zh-cn">大小的未格式化磁盘。</span></p> <p> </p> <p><img src="//image.lceda.cn/pullimage/6SagcH7jloG5pGpedmIV9b8zMcg5pM2jApJfqQHb.png" alt="" width="947" height="555" /></p> <p><span lang="zh-cn" xml:lang="zh-cn">这里推荐使用</span> Disk Genius <span lang="zh-cn" xml:lang="zh-cn">来创建分区:</span>16MB GPT <span lang="zh-cn" xml:lang="zh-cn">分区,</span>FAT16  Sector512Bytes<span lang="zh-cn" xml:lang="zh-cn">。就是说,前面</span> 16MB <span lang="zh-cn" xml:lang="zh-cn">我们开启</span>FAT <span lang="zh-cn" xml:lang="zh-cn">分区暴露出来,后面</span> 16MB <span lang="zh-cn" xml:lang="zh-cn">的空间我们用其中的</span> 2MB<span lang="zh-cn" xml:lang="zh-cn">来作为数据交换空间使用。这样的好处是:</span></p> <p>1.<span lang="zh-cn" xml:lang="zh-cn">可以用作</span> UEFI <span lang="zh-cn" xml:lang="zh-cn">启动盘,我们也可以将一些工具直接放置在上面;</span></p> <p>2.<span lang="zh-cn" xml:lang="zh-cn">数据交换空间放在未分区的位置可以避免操作系统的缓存机制;</span></p> <p><img src="//image.lceda.cn/pullimage/ZH9eB5l4kEBfu48WeS3pTnhGkbJW8RnEwEC0RUuj.png" alt="" /></p> <p><span lang="zh-cn" xml:lang="zh-cn">上述做好了之后我们需要将这个硬盘制作为镜像文件,这里使用一个免费软件</span> HxD<span lang="zh-cn" xml:lang="zh-cn">。特别注意需要用管理员权限启动。</span></p> <p><img src="//image.lceda.cn/pullimage/f3IdXiC2FTFSU57XjVS0OoYFSr1lfTJdo7bZ9jIA.png" alt="" /></p> <p>Tools->Open Disk <span lang="zh-cn" xml:lang="zh-cn">中选择中这个磁盘</span></p> <p><img src="//image.lceda.cn/pullimage/9fGQleQyIW1iMD7sedeogr8nJwOBD6GsCsAeA0tZ.png" alt="" width="674" height="526" /></p> <p><span lang="zh-cn" xml:lang="zh-cn">之后使用</span> File->Save As <span lang="zh-cn" xml:lang="zh-cn">保存为一个文件即可。</span></p> <p><img src="//image.lceda.cn/pullimage/Pk9KFv7LnVEXmDHLnZ0OyXeAORxNsyiygkTxRNmO.png" alt="" width="1066" height="474" /></p> <p><span lang="zh-cn" xml:lang="zh-cn">通过这个磁盘镜像文件我们可以完整的模拟这个磁盘,当有读取命令到来时,我们可以根据命令中给出来的偏移返回文件中的内容即可。接下来的问题是:我们需要找到一种方法来进行“压缩”,因为这个镜像文件有</span>64MB <span lang="zh-cn" xml:lang="zh-cn">大小,而</span>ESP32 S2<span lang="zh-cn" xml:lang="zh-cn">只有</span>4MB <span lang="zh-cn" xml:lang="zh-cn">的空间。经过观察可以发现,镜像文件中大部分内容都是</span>00<span lang="zh-cn" xml:lang="zh-cn">,因此这里采用的方法是:以</span>512<span lang="zh-cn" xml:lang="zh-cn">字节为单位,用程序扫描生成的镜像文件,如果内容不为</span>0<span lang="zh-cn" xml:lang="zh-cn">就记录下来,否则抛弃。</span></p> <p> </p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt pap-left-indent-1.6em" style="line-height:1.8;"><span lang="zh-cn" xml:lang="zh-cn">处理之后的结果是</span> .h <span lang="zh-cn" xml:lang="zh-cn">文件,其中有</span>2<span lang="zh-cn" xml:lang="zh-cn">个数组,一个是不同扇区的数据定义,示例如下:</span></p> <p>const unsigned char Sector[1704][512]  = {</p> <p>{</p> <p>//No. 0 Sector: 0x0</p> <p>0x33,0xC0,0x8E,0xD0,0xBC,0x00,0x7C,0x8E,0xC0,0x8E,0xD8,0xBE,0x00,0x7C,0xBF,0x00,</p> <p>0x06,0xB9,0x00,0x02,0xFC,0xF3,0xA4,0x50,0x68,0x1C,0x06,0xCB,0xFB,0xB9,0x04,0x00,</p> <p>0xBD,0xBE,0x07,0x80,0x7E,0x00,0x00,0x7C,0x0B,0x0F,0x85,0x0E,0x01,0x83,0xC5,0x10,</p> <p>0xE2,0xF1,0xCD,0x18,0x88,0x56,0x00,0x55,0xC6,0x46,0x11,0x05,0xC6,0x46,0x10,0x00,</p> <p>0xB4,0x41,0xBB,0xAA,0x55,0xCD,0x13,0x5D,0x72,0x0F,0x81,0xFB,0x55,0xAA,0x75,0x09,</p> <p>………….}</p> <p>………………</p> <p>{</p> <p>//No. 1702 Sector: 0xffff</p> <p>0x45,0x46,0x49,0x20,0x50,0x41,0x52,0x54,0x00,0x00,0x01,0x00,0x5C,0x00,0x00,0x00,</p> <p>0x2B,0xC1,0xF0,0x2A,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,</p> <p>0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,</p> <p>0xDE,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x6F,0xFB,0x30,0xB9,0xEC,0x2D,0x4A,</p> <p>……..}};</p> <p><span lang="zh-cn" xml:lang="zh-cn">另外一个是扇区索引,例如:</span></p> <p>int SPIRomIndex[1703]= {0x0,0x1,0x2,0x80,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x101,0x102,0x103,0x104,0x105,0x106,</p> <p>0x107,0x180,0x1A0,0x1A1,0x1A2,0x1A3,0x1A4,0x1A5,0x1A6,0x1A7,0x1A8,0x1A9,0x1AA,0x1AB,0x1AC,0x10AD,0x1AE,</p> <p>0x1AF,0x1B0,0x1B1,0x1B2,0x1B3,0x1B4,0x1B5,0x1B6,0x1B7,0x1B8,0x1B9,0x1BA,0x1BB,0x1BC,0x1BD,0x1BE,0x1BF,</p> <p>0x1C0,0x1C1,0x1C2,0x1C3,0x1C4,0x1C5,0x1C6,0x1C7,0x1C8,0x1C9,0x1CA,0x1CB,0x1CC,0x1CD,0x1CE,0x1CF,0x1D0,</p> <p>……..}</p> <p><span lang="zh-cn" xml:lang="zh-cn">比如,当前命令要访问</span> 0 <span lang="zh-cn" xml:lang="zh-cn">号扇区,那么首先在</span>SPIRomIndex<span lang="zh-cn" xml:lang="zh-cn">中搜索</span> 0<span lang="zh-cn" xml:lang="zh-cn">,</span> <span lang="zh-cn" xml:lang="zh-cn">可以在第一个位置找到,意思是</span>Sector[0][512] <span lang="zh-cn" xml:lang="zh-cn">就是</span>0<span lang="zh-cn" xml:lang="zh-cn">号扇区的内容;例如,命令要求访问</span> 0x03 <span lang="zh-cn" xml:lang="zh-cn">扇区,而</span>SPIRomIndex[]<span lang="zh-cn" xml:lang="zh-cn">中没有等于</span>3<span lang="zh-cn" xml:lang="zh-cn">的值,因此直接返回全</span>0x00 <span lang="zh-cn" xml:lang="zh-cn">的数据即可;再例如,命令中要访问</span> 0x80 <span lang="zh-cn" xml:lang="zh-cn">扇区,而</span>SPIRomIndex[3]==0x80<span lang="zh-cn" xml:lang="zh-cn">,因此,我们需要的数据在</span>Sector[3] <span lang="zh-cn" xml:lang="zh-cn">中,通过这样的方法,我们在一个</span>4.4MB <span lang="zh-cn" xml:lang="zh-cn">的文件中,定义了</span> 32MB<span lang="zh-cn" xml:lang="zh-cn">磁盘镜像的数据。对应的代码是:</span></p> <p>int32_t IsInRomSector(uint32_t lba) {</p> <p>      for (int32_t i = 0; i < sizeof(SPIRomIndex)/sizeof(int); i++) {</p> <p>        if (lba == SPIRomIndex[i]) {</p> <p>          return i;</p> <p>        } else if (lba < SPIRomIndex[i]) {</p> <p>          return 0xFFFFFFFF;</p> <p>        }</p> <p>      }</p> <p>      return 0xFFFFFFFF;</p> <p>}</p> <p> </p> <p><span lang="zh-cn" xml:lang="zh-cn">另外,在</span> ESP32 S2 <span lang="zh-cn" xml:lang="zh-cn">中将对于</span>U<span lang="zh-cn" xml:lang="zh-cn">盘</span>32896 <span lang="zh-cn" xml:lang="zh-cn">到</span>32896+4094<span lang="zh-cn" xml:lang="zh-cn">扇区上的读写全部发送到</span> pSRAM<span lang="zh-cn" xml:lang="zh-cn">上。我们使用了</span> pSRAM <span lang="zh-cn" xml:lang="zh-cn">上第</span>2<span lang="zh-cn" xml:lang="zh-cn">个到</span>4094<span lang="zh-cn" xml:lang="zh-cn">个扇区用于存储数据,原因是</span>pSRAM<span lang="zh-cn" xml:lang="zh-cn">虽然有</span> 2MB <span lang="zh-cn" xml:lang="zh-cn">大小,但是起始和结尾处存在有用的数据,不能使用。因此,实际使用的</span> pSRAM <span lang="zh-cn" xml:lang="zh-cn">大小是</span> 2*1024*1024-2*512 <span lang="zh-cn" xml:lang="zh-cn">字节。这部分的代码如下:</span></p> <p>// Callback invoked when received READ10 command.</p> <p>// Copy disk's data to buffer (up to bufsize) and return number of copied bytes.</p> <p>int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize)</p> <p>{</p> <p>  (void) lun;</p> <p>  //uint8_t* addr = &msc_disk[lba * 512] + offset;</p> <p>  //memcpy(buffer, addr, bufsize);</p> <p>    log_v("read lba %X, offs: %d, bufs %d", lba, offset,bufsize);</p> <p>  if (lba==32896+4096) {</p> <p>      memset(buffer,0,512);</p> <p>      memcpy(buffer,&StoreInfo,sizeof(StoreInfo));</p> <p>      return bufsize;</p> <p>    }</p> <p>  // <span lang="zh-cn" xml:lang="zh-cn">如果读取发生在特定范围那么就在</span> psRam<span lang="zh-cn" xml:lang="zh-cn">上读取</span> </p> <p>  if ((lba<32896+4094)&&(lba>=32896)) {</p> <p>      memcpy(buffer,&psRam[(lba-32896)*512+512],bufsize);</p> <p>      return bufsize;</p> <p>    }</p> <p>  uint32_t SectorIndex = IsInRomSector(lba);</p> <p>  if (SectorIndex != 0xFFFFFFFF) {</p> <p>     memcpy(buffer, &Sector[SectorIndex][0], bufsize);</p> <p>     log_v("reply %d", SectorIndex);</p> <p>  } else {</p> <p>     memset(buffer,0, bufsize);</p> <p>     log_v("reply all 0");</p> <p>  }</p> <p> </p> <p>  return bufsize;</p> <p>}</p> <p> </p> <p>// Callback invoked when received WRITE10 command.</p> <p>// Process data in buffer to disk's storage and return number of written bytes</p> <p>int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize)</p> <p>{</p> <p>  (void) lun;</p> <p> </p> <p>  if (lba==32896+4096) {</p> <p>      memcpy(&StoreInfo,buffer,sizeof(StoreInfo));</p> <p>      return bufsize;</p> <p>    }</p> <p>  // <span lang="zh-cn" xml:lang="zh-cn">如果写入发生在特定范围那么就在</span> psRam<span lang="zh-cn" xml:lang="zh-cn">上写入</span> </p> <p>  if ((lba<32896+4094)&&(lba>=32896)) {</p> <p>      memcpy(&psRam[(lba-32896)*512+512],buffer,bufsize);</p> <p>      return bufsize;</p> <p>    }   </p> <p> </p> <p>  return bufsize;</p> <p>}</p> <p><span lang="zh-cn" xml:lang="zh-cn">为了传输文件,设计一个结构体保存文件信息,定义如下</span>:</p> <p>typedef struct</p> <p>{</p> <p>  unsigned long Signatures;  // Offset:0-3 //"LABZ"</p> <p>  unsigned long length;      // Offset:4-7</p> <p>  char          ver[4];      // Offset:8-11</p> <p>  unsigned long mono;        // Offset:12-15</p> <p>  char          filename[32];//Offset:16-47</p> <p>  char          reserved[16];//Offset:48-63</p> <p>} StoreInfo_struct;</p> <p><span lang="zh-cn" xml:lang="zh-cn">其中包括了文件的大小,名称信息,此外还预留了</span> ver<span lang="zh-cn" xml:lang="zh-cn">作为版本信息,</span>mono<span lang="zh-cn" xml:lang="zh-cn">是预留的一个单增数值,二者目前还没有用途。这个结构体是放置在</span>ESP32 S2 <span lang="zh-cn" xml:lang="zh-cn">模拟</span>U<span lang="zh-cn" xml:lang="zh-cn">盘的</span>32896+4096=36,992<span lang="zh-cn" xml:lang="zh-cn">(偏移</span>  0x121 0000<span lang="zh-cn" xml:lang="zh-cn">)位置上的。在上面的代码中也可以看到对此的特殊处理。</span></p> <p><span lang="zh-cn" xml:lang="zh-cn">接下来介绍串口访问的设计,相对于前面</span>U<span lang="zh-cn" xml:lang="zh-cn">盘,这部分复杂得多,数据的收发都必须使用</span>Checksum<span lang="zh-cn" xml:lang="zh-cn">来进行校验。这部分的设计如下:</span></p> <p> </p> <p><span lang="zh-cn" xml:lang="zh-cn"><img src="//image.lceda.cn/pullimage/UAyQJq4IzlyddmNnpZ7K2wsfclfb1brxS2ORJtuU.png" alt="" /></span></p> <p><span lang="zh-cn" xml:lang="zh-cn">命令</span> 0x55: ESP32 S2<span lang="zh-cn" xml:lang="zh-cn">接收数据,收到后进行</span> Checksum <span lang="zh-cn" xml:lang="zh-cn">校验,校验方法是:全部数据(</span>4K+2Bytes<span lang="zh-cn" xml:lang="zh-cn">)相加后结果应该为</span>0<span lang="zh-cn" xml:lang="zh-cn">;</span></p> <p><span lang="zh-cn" xml:lang="zh-cn">命令</span> 0xAA: ESP32 S2<span lang="zh-cn" xml:lang="zh-cn">发送数据,数据是</span> 4K + 2Byte<span lang="zh-cn" xml:lang="zh-cn">的</span> Checksum</p> <p><span lang="zh-cn" xml:lang="zh-cn">命令</span>VRS<span lang="zh-cn" xml:lang="zh-cn">:</span>ESP32 S2<span lang="zh-cn" xml:lang="zh-cn">返回当前的版本信息</span></p> <p><span lang="zh-cn" xml:lang="zh-cn">命令</span> 0x808080: ESP32 S2 <span lang="zh-cn" xml:lang="zh-cn">发送当前的</span> StoreInfo_struct <span lang="zh-cn" xml:lang="zh-cn">结构体给上位机</span></p> <p><span lang="zh-cn" xml:lang="zh-cn">命令</span> 0x808080:<span lang="zh-cn" xml:lang="zh-cn">上位机发送当前的</span> StoreInfo_struct <span lang="zh-cn" xml:lang="zh-cn">结构体给</span>ESP32 S2</p> <p> </p> <p><span lang="zh-cn" xml:lang="zh-cn">所有的命令加参数都是</span>3 Bytes <span lang="zh-cn" xml:lang="zh-cn">长度,上位机发送命令后,需要</span>ESP32S2<span lang="zh-cn" xml:lang="zh-cn">回复收到的命令,比如相同后才能继续(因为我发现一些情况下</span>ESP32 S2 <span lang="zh-cn" xml:lang="zh-cn">收到的命令和发送出去的不同),代码如下:</span></p> <p>// <span lang="zh-cn" xml:lang="zh-cn">接收命令,如果超时返回全</span> 0xFF</p> <p>void receiveCMD() {</p> <p>  if (Serial.available() != 0) {</p> <p>    if (DEBUGMODE) {</p> <p>      Serial1.println(Serial.available());</p> <p>    }</p> <p>  }</p> <p>  if (Serial.available() >= CMD_MAX) {</p> <p>    Serial.readBytes(CMD, CMD_MAX);</p> <p> </p> <p>    if (DEBUGMODE) {</p> <p>      Serial1.println("Get CMD_MAX");</p> <p>    }</p> <p>    if (DEBUGMODE) {</p> <p>      Serial1.print("rcvBuffer[i]: ");</p> <p>    }</p> <p>    // <span lang="zh-cn" xml:lang="zh-cn">重新将命令发回上位机,等待确认</span></p> <p>    for (int i = 0; i < CMD_MAX; i++) {</p> <p>      Serial.write(CMD[i]);</p> <p>      if (DEBUGMODE) {</p> <p>        Serial1.print((char)CMD[i]);</p> <p>      }</p> <p>    }</p> <p>    if (DEBUGMODE) {</p> <p>      Serial1.println("");</p> <p>    }</p> <p>    if (upperConfirm() != true) {</p> <p>      memset(CMD, 0xFF, CMD_MAX);</p> <p>      return ;</p> <p>    }</p> <p> </p> <p>    // <span lang="zh-cn" xml:lang="zh-cn">到这里表示正常</span></p> <p>  } else {</p> <p>    //<span lang="zh-cn" xml:lang="zh-cn">超时返回全</span> 0xFF</p> <p>    memset(CMD, 0xFF, CMD_MAX);</p> <p>  }</p> <p> </p> <p>  return ;</p> <p>}</p> <p><span lang="zh-cn" xml:lang="zh-cn">总结一下,如果你想制作一个同样的设备,需要如下步骤:</span></p> <p>1.      <span lang="zh-cn" xml:lang="zh-cn">制作</span> PCB</p> <p>2.      <span lang="zh-cn" xml:lang="zh-cn">焊接</span></p> <p>3.      Arduino <span lang="zh-cn" xml:lang="zh-cn">烧写</span> ESP32 <span lang="zh-cn" xml:lang="zh-cn">代码</span></p> <p>4.      <span lang="zh-cn" xml:lang="zh-cn">烧写</span> CH340B  EEPROM</p> <p>5.      USB A <span lang="zh-cn" xml:lang="zh-cn">公头端是</span> COM <span lang="zh-cn" xml:lang="zh-cn">转</span> USB <span lang="zh-cn" xml:lang="zh-cn">设备,用于</span>Windows <span lang="zh-cn" xml:lang="zh-cn">主机使用串口通讯程序发送</span>/<span lang="zh-cn" xml:lang="zh-cn">接收数据</span></p> <p>6.      USB B <span lang="zh-cn" xml:lang="zh-cn">母头端是</span> USB MSD <span lang="zh-cn" xml:lang="zh-cn">设备,用于</span> UEFI Shell <span lang="zh-cn" xml:lang="zh-cn">发送</span>/<span lang="zh-cn" xml:lang="zh-cn">接收数据</span></p> <p> </p> <h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;">*6、BOM清单</h3> <hr class="horizontal-splitline normal-bold-2" /><table style="border-collapse:collapse;width:480pt;" border="0" width="640" cellspacing="0" cellpadding="0"><tbody><tr style="height:14.4pt;"><td style="height:14.4pt;width:48pt;" width="64" height="19">ID</td> <td style="width:48pt;" width="64">Name</td> <td style="width:48pt;" width="64">Designator</td> <td style="width:48pt;" width="64">Footprint</td> <td style="width:48pt;" width="64">Quantity</td> <td style="width:48pt;" width="64">Manufacturer Part</td> <td style="width:48pt;" width="64">Manufacturer</td> <td style="width:48pt;" width="64">Supplier</td> <td style="width:48pt;" width="64">Supplier Part</td> <td style="width:48pt;" width="64">Price</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">1</td> <td>10uf</td> <td>C1,C7,C8</td> <td>C1206</td> <td align="right">3</td> <td>CC1206JRNPOBBN270</td> <td>YAGEO</td> <td>LCSC</td> <td>C326944</td> <td align="right">0.1755</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">2</td> <td>0.1uf</td> <td>C2,C3,C4,C9,C10</td> <td>C1206</td> <td align="right">5</td> <td>CC1206JRNPOBBN270</td> <td>YAGEO</td> <td>LCSC</td> <td>C326944</td> <td align="right">0.1755</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">3</td> <td>EN</td> <td>EN</td> <td>SW-SMD_L4.0-W2.9-LS5.0</td> <td align="right">1</td> <td>TS342A2P-WZ</td> <td>SHOU HAN</td> <td>LCSC</td> <td>C557591</td> <td align="right">0.25</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">4</td> <td>BSMD1206-050-6V</td> <td>F1</td> <td>F1206</td> <td align="right">1</td> <td>BSMD1206-050-6V</td> <td>BHFUSE</td> <td>LCSC</td> <td>C883122</td> <td align="right">0.1895</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">5</td> <td>GPIO0</td> <td>GPIO0</td> <td>SW-SMD_L4.0-W2.9-LS5.0</td> <td align="right">1</td> <td>TS342A2P-WZ</td> <td>SHOU HAN</td> <td>LCSC</td> <td>C557591</td> <td align="right">0.25</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">6</td> <td>204-10SURT/S530-A3</td> <td>LED1,LED2,LED3</td> <td>LED-TH_BD4.3-P2.54</td> <td align="right">3</td> <td>204-10SURT/S530-A3</td> <td>Everlight Elec</td> <td>LCSC</td> <td>C282135</td> <td align="right">0.2304</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">7</td> <td>SW UART</td> <td>P1</td> <td>HDR-TH_3P-P2.54-V-F</td> <td align="right">1</td> <td>Header-Female-2.54_1x3</td> <td>Boom Precision Elec</td> <td>LCSC</td> <td>C146243</td> <td align="right">0.3032</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">8</td> <td>SS8050_C2150</td> <td>Q1,Q2</td> <td>SOT-23-3_L2.9-W1.3-P1.90-LS2.4-BR</td> <td align="right">2</td> <td>SS8050</td> <td>CJ</td> <td>LCSC</td> <td>C2150</td> <td align="right">0.1238</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">9</td> <td>10K</td> <td>R1,R2,R3,R4</td> <td>R1206</td> <td align="right">4</td> <td>AECR1206F120KK9</td> <td>ResistorToday</td> <td>LCSC</td> <td>C352156</td> <td align="right">0.0443</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">10</td> <td>3.3K</td> <td>R5,R6,R7</td> <td>R1206</td> <td align="right">3</td> <td>PTFR1206B10K0P9</td> <td>ResistorToday</td> <td>LCSC</td> <td>C351536</td> <td align="right">1.0474</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">11</td> <td>ESP32-S2-WROVER(4MB)</td> <td>U1</td> <td>WIFI-SMD_ESP32-S2-WROVER-I</td> <td align="right">1</td> <td>ESP32-S2-WROVER(4MB)</td> <td>Espressif Systems</td> <td>LCSC</td> <td>C701333</td> <td align="right">20.47</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">12</td> <td>AMS1117-3.3</td> <td>U2</td> <td>SOT-223</td> <td align="right">1</td> <td>AMS1117-3.3</td> <td>AMS</td> <td>LCSC</td> <td>C6186</td> <td align="right">1.5243</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">13</td> <td>CH340B</td> <td>U3</td> <td>SOIC-16_L9.9-W3.9-P1.27-LS6.0-BL</td> <td align="right">1</td> <td>CH340B</td> <td>WCH</td> <td>LCSC</td> <td>C81010</td> <td align="right">7.26</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">14</td> <td>U-B-M4DD-W-1</td> <td>USB1</td> <td>USB-B-TH_U-B-M4DD-W-1</td> <td align="right">1</td> <td>U-B-M4DD-W-1</td> <td>Korean Hroparts Elec</td> <td>LCSC</td> <td>C530600</td> <td align="right">2.04</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">15</td> <td>USB-212-BCW</td> <td>USB2</td> <td>USB-A-SMD_USB-212-BCW</td> <td align="right">1</td> <td>USB-212-BCW</td> <td>XUNPU</td> <td>LCSC</td> <td>C720521</td> <td align="right">0.4174</td> </tr><tr style="height:14.4pt;"><td style="height:14.4pt;" align="right" height="19">16</td> <td>1x2</td> <td>USB_POWER1,USB_POWER2</td> <td>HDR-TH_2P-P2.54-V</td> <td align="right">2</td> <td>826629-2</td> <td>TE Connectivity</td> <td>LCSC</td> <td>C86471</td> <td align="right">0.6015</td> </tr></tbody></table><p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"> </p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"><span style="color:#95a5a6;font-size:14px;">注:项目涉及的BOM清单。这个位置请上传BOM的截图。清单详情请以PDF的格式上传到附件中。建议包括型号、品牌、名称、封装、采购渠道、用途等内容。具体内容和形式应以表达清楚项目构成为准。</span></p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"> </p> <h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;">*7、大赛LOGO验证</h3> <hr class="horizontal-splitline normal-bold-2" /><p style="line-height:1.8;"> </p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"><img src="//image.lceda.cn/pullimage/Kfek2kgPDjYzHAv2VKoVbOgW9qJWb0LCrnviptiS.jpeg" alt="正面" width="1200" height="1036" /></p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"><img src="//image.lceda.cn/pullimage/Xn3rxM1ABdy0Tbs5M2MawJhxLXpFgCFUKQ3tifr2.jpeg" alt="背面" width="1094" height="820" /></p> <h3 class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;">* 8、演示您的项目并录制成视频上传</h3> <hr class="horizontal-splitline normal-bold-2" /><p style="line-height:1.8;"> </p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"><span style="color:#95a5a6;font-size:14px;">视频要求:请横屏拍摄,分辨率不低于1280×720,格式Mp4/Mov,单个视频大小限100M内;</span></p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"><span style="color:#95a5a6;font-size:14px;">视频标题:立创电赛:{项目名称}-{视频模块名称};如立创电赛:《自动驾驶》-团队介绍。</span></p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"> </p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"><span style="font-size:14px;">更多详情:<a href="/posts/06c94d90c2c447dfbd9ed7339ff4a5b1">https://diy.szlcsc.com/posts/06c94d90c2c447dfbd9ed7339ff4a5b1</a></span></p> <p class="paragraph text-align-type-left pap-line-1.3 pap-line-rule-auto pap-spacing-before-3pt pap-spacing-after-3pt" style="line-height:1.8;"> </p> </div>

文档

BOM

暂无

附件

暂无

评论(2)

成功
工程所有者当前已关闭评论
LCDS 回复

 记得上传logo验证图片哟~

Zoologist 回复

@LCDS  刚才上传了

goToTop
svg-battery svg-battery-wifi svg-books svg-more svg-paste svg-pencil svg-plant svg-ruler svg-share svg-user svg-logo-cn svg-double-arrow