分类 硬件 下的文章

前两周终于把嵌入式系统的期末作业给交了,老师大发慈悲给了个及格,被课程设计这把达摩克利斯之剑悬在头顶的难受日子终于过去了。秉持做事有始有终的原则,在此记录一下我在这门课程,或者说是在这个方向上总结的知识吧。

甲 嵌入式是什么?

首先需要一点想象力来描述嵌入式的使用场景:

提到“嵌入”一词,相信联想到戒指上 镶嵌 钻石这个场景不是什么难事,想必读者也能轻松接受钻石往往比指环本身小的事实。这也是我对嵌入式理解的一个切入点,即小而精的系统,在我们的语境下,这还是一个计算机系统。

再看看百度上的定义:

嵌入式系统是以应用为中心,以现代计算机技术为基础,能够根据用户需求(功能、可靠性、成本、体积、功耗、环境等)灵活裁剪软硬件模块的专用计算机系统。

这是某个权威组织给嵌入式系统下的定义,但我忘了是哪个了。显然,在这条标准定义中,也着重强调了系统的灵活性,除功能和可靠性可能与嵌入式系统的体积有正相关外,我认为,其余需求都可以总结为四个字:越小越好。甚至为了达成这个目的,嵌入式系统舍弃了x86生态引以为傲的模块化、标准化模式,每搭一个新系统就要重做一大堆 轮子 (意义不大但不可避免的工作,如硬件驱动等),导致如今作为主要应用场景之一的智能手机,无可避免地走上了“只换不修”、“不能升级,只能重买”的道路,严重怀疑手机厂商是故意的

因而,如何设计像麻雀一样小而五脏俱全的计算机系统,正是嵌入式系统所追求的。

乙 嵌入式要做什么?

嵌入式开发可以分为两个部分,硬件开发和软件开发。

硬件开发是嵌入式系统主要区别于一般计算机系统的特点,主要表现在为了裁剪系统规格,需要为每一个应用场景专门设计系统原理图,并设计对应的电路板。(P.S. 正是在这里,嵌入式系统引入了微电子学的要素,电源和晶振电路的参数要自己算,使嵌入式系统这门课成为了我本学年最折磨的一门课QwQ)

电路板设计的过程中,需要根据电子元件的物理和电气属性,结合应用场景,合理选择板型、制作并排布焊盘,为可能需要的外设引出合适的接口,然后完成走线工作。设计完成后的电路板可以导出工业标准的文件,交给PCB厂打样生产,做成可以焊接使用的电路板实物;还可以寻找SMT等贴片焊接厂家,将设计过程中使用的电子元器件导出成BOM(Bill Of Material,物料清单)与摆设信息(如pick place文件等),让厂家代为焊接,拿到手就是一片开箱即用的板子了。

软件开发与x86平台上的开发流程有着一定的区别。在编程上,绝大部分工作都使用C/C++完成,由相应的交叉编译工具链生成二进制代码(不是ELF也不是COFF),更不可能出现动态链接;在运行上,嵌入式程序直接以二进制的形式烧录到Flash芯片上,CPU可直接寻址执行,不存在像x86一样从磁盘读进内存,再读进CPU缓存后执行的漫长数据通路;在设计上,由于在嵌入式系统中,资源通常比较紧张,操作系统不是刚需(轻量的RTOS实时操作系统甚至可以被称为线程库),单线程的程序往往足以达到嵌入式系统的设计需求。

这里可以强调的一点是,嵌入式系统(主要考虑ARM)的内存地址空间是连续的,但介质可以是不连续的,即DRAM和NAND/NOR等通常被视为运存和外存的两种介质可以映射到同一地址空间的不同区域。(NOR Flash虽然是通常意义上的外存芯片,但由于其支持字节寻址,是支持XIP(eXecute-In-Place,片内执行,意味着介质可作内存使用)的,但性能较低、成本较高)

丙 硬件开发的具体步骤

硬件开发的主要任务是原理图和电路板的设计,在使用计算机辅助设计的情况下,绝大部分工作都在EDA(Electronic Design Automation,电子设计自动化)工具中完成——没错,就是漂亮国卡咱脖子的那个。除了能够替代人力完成绘图这种基本工作外,EDA软件还可以提供自动布线、(手动)布线检查、逻辑综合、仿真等多种人力难以快速办到的功能。当然,对于我们这种初级电路板设计来说,其中的大部分功能都不一定用得到就是了=w=

下面列出的硬件开发步骤中,二-六步都是在EDA软件中完成的,我使用的是Altium Designer 21。当然,工具不能成为限制开发的理由,真正要搞大新闻的时候,还是不要跟风,选择合适的工具才是上策。

还是码一下吧,我学Altium Designer主要看的是av62785020,虽然讲得有点啰嗦,但是还是很全面清晰了。

一 器件选型

这个部分和我们平常自己买电脑时,挑选配置的工作非常相似。稍微了解一点买电脑的话,买之前要做的第一件事情就是做规划:想要什么样的尺寸、需要什么样的功能、打算花多少钱,等等。

这里的器件选型工作也是一样的,先要完成一些预备工作,准备足够的信息指导自身完成选择。首先分析设计需求,抽象地提出组成目标系统所需的模块,比如供电所需的电源模块、通信所需的Wifi/蓝牙模块、信息输入所需的传感器模块、信息输出所需的音频/视频模块等等,并理清这些模块之间的连接关系。

其次要考虑的是应用场景,将其中最为重要的特征筛选出来,用以指导具体器件的选择:如果想做贴身设备,如电子手环,就必须在后续选型中将重量(轻)、体积(小)、电源(自带电池、低功耗)作为选型的首要依据,可适当选择性能偏低的芯片作为权衡;如果想做高性能设备,如 漏油器 路由器,就必须在后续选型中将性能(高)作为首要依据,而无需过多考虑重量、体积、电源等参数;如果想做的设备要外接大量模块的话,就必须选择引脚足够多的主控芯片(微控制器),以确保主控可以直接控制所有需要的外围设备。

接下来就是根据上述步骤收集的信息完成芯片的选择了。这个过程需要了解一下上面自己所提出的功能模块对应的具体模块的专业名称,比如:对于电源模块来说,完成常见的5V-3.3V电平转换的模块叫做 稳压器,诸如3.7-3.3V一类压差小于1.7V的电平转换模块叫 低压差稳压器(LDO,Low-DrOpout regulator);开发板上外接针脚用的排针,金属针凸出来的叫排针 废话,塑料凹进去的叫排母。其实遇到专业名词的比例并不大,但是一旦遇到了的话,往往会因为没有门路,老半天找不到自己想找的器件。一种曲线救国的方式是用自己的大白话在搜索引擎或者淘宝上搜,有概率能够通过一些推荐算法摸到这些专业名词。

当然,在芯片选型的过程中,还可以结合成本等非主要因素,适当地调整芯片的选型。需要注意的是,芯片并不一定越小越便宜,而是产量越大越便宜,有时候小碗可能还比大碗贵= =

P.S. 大部分嵌入式主控芯片都自带大小不等的片内Flash(~1MB)和RAM(数十KB),如果程序不是特别大的话甚至可以不用考虑外接存储芯片。

二 原理图制作

选定了芯片之后,实际上电路的设计就完成了一大半了。这是因为芯片针脚一般具有固定功能,并且极少有冗余的情况(毕竟要追求小而精嘛,wx:你再骂?),完成功能所需的连线模式可以说是完全固定下来了,原理图所需要做的事情就是在上述提到的抽象模块图的基础上标出确切的针脚,然后指明不同模块之间的针脚连接方式。到这一步为止,电路设计还是停留在原理阶段。

三 焊盘制作

焊盘就是电路板上用于焊接贴片元件的焊接点,一方面将芯片针脚引出,参与电路板电气网络的互联;另一方面,焊接点能够提供足够的粘合力,将原件固定在电路板上。如果说原理图提供了元器件针脚的定义和连接方式的话,焊盘则依据器件的引脚物理排布为电路板设计焊接点——尺寸、形状必须与实物完全一致。

如果见过集成电路板的话,很容易能够理解焊盘就是电路板上裸露出来的、通常是黄偏红色的金属部分。实际上这就是电路板上用于焊接原件和导电的覆铜部分(其余部分刷有颜料以绝缘)。与传统电路板不同的是,嵌入式集成电路板使用贴片元件较多,贴片封装一方面减小封装体积,另一方面减小焊接难度,然而这给手动焊接带来了不小麻烦,所以一般不建议自己手焊贴片元件= =

贴片焊盘的制作在Altium Designer中可以使用Tools菜单下名为IPC Compliant Footprint Wizard的工具,快速利用现有模板生成贴片元件的焊盘,元器件的对应参数可以查其生产商的数据手册获得。至于5V电源接口这种带过孔的我就不会画了,可以考虑去网上找。这里推荐一个叫SnapEDA的网站,注册个账号就能免费下载不少常用的焊盘。

由于焊盘这块我大部分是抄作业(指用别人做好的)和工具生成,经验积累不多,故在此简略带过。

四 焊盘布局

电路板绘制通常包含焊盘绘制与布线两个部分。显然原理图中的每个模块都是要对应到电路板上的真实器件的,或许是芯片、插口(如圆口电源、USB等)、排针,也可能是电容、电阻、晶振等基础电子元件。因而在电路板绘制时,要把原理图中元件对应的焊盘实例化到电路板上,然后再完成布线工作。

手动在电路板上为每一个元件生成焊盘是一件麻烦的事情,即使焊盘已经实现制做好了。好在Altium Designer提供了自动生成焊盘的功能:在完成上一步的焊盘设计后,我们可以回到更前一步的原理图设计中,将每个元件的原理图与对应的焊盘关联,然后在PcbDoc中使用Design菜单下的Import Changes From ***.PrjPcb一键导入原理图中所有元件对应的焊盘。

焊盘生成完成后,便要做好布局。焊盘布局通常遵循以下规则:

  1. 遵循先大后小的原则(先确定大元器件的位置,小的可以挤一挤);
  2. 主控放在电路板中央;
  3. 晶振离主控尽可能近,离电路板边缘尽可能远;
  4. 电源接口放在电路板边缘(废话)

此时只需要排布好焊盘之间的大致相对位置即可,精细对齐工作可以在摆好所有焊盘之后一起完成,Altium Designer提供了对齐的快捷键,可以在做这一步工作的时候去具体学习一下。

五 布线

布线是电路板设计中的最后一步,也可以说是自动化难度最高的一步。布线要做的事情就是按照原理图中的设计完成线网的连接。布线通常受到电路板的限制——在低成本情况下,所使用的印刷电路板是双层或四层的,在这两种电路板中,通常只留有两层可供信号走线(四层板的另外两层分别用作电源和接地)。在这种情况下,为了防止线与线之间交叉,通常需要使用过孔,使得线路适时更换所在覆铜层以避免线路的直接交叉。但是,过孔毕竟有着不同于导线的物理形式,会对某些场景产生意想不到的副作用,比如高频信号场景下,过孔近似于设立了一根天线,因而要根据线路的电气属性合理设置过孔的数量和位置。通常布线遵循如下规则:

  1. 线路拐角为135°(方便制作印刷电路板时液体材料的流动,EDA软件通常原生遵循这个规则);
  2. 高频线路尽量不走过孔,一般信号线路的过孔尽量控制在2个以内;
  3. 电源线适当地比信号线粗一点;
  4. 没有走线的大片空白区域最好以电源或地电位覆铜。

其余的规则还包括线与线之间要保持足够的距离(工艺要求+防止干扰)等等,专业的总结应该会提到这些注意点的。

布完线之后,可以使用Reports里的Board Information,勾选Routing Information后生成报告,就可以检查还有没有遗漏没连接的线路了。具体怎么找漏线的位置可以再去搜一下相关文章。

六 导出生产用文件

完成布线后的电路板与后续实际生产出来的电路板就基本一致了,实际上我们也可以将设计电路板时所使用的一系列PcbDoc直接交给PCB厂用于生产。然而,防人之心不可无,为了避免某些情况下PCB厂无意泄露或有意窃取电路板上的设计信息,对电路板设计者产生知识产权上的利益损失,一般来说设计者希望提交一份不可修改、附加信息尽可能少的文件用于生产。所幸资本家早早考虑到了这一点,目前用于PCB生产的有一种名为Gerber的文件格式,类似于PCB界的PDF,也是一种与软件无关的PCB电路板描述格式。

给PCB厂(电路板生产)一般需要准备如下文件:Gerber(电路板蚀刻)、RectHoles(钻孔)、TestPoint(电气测试)、PickPlace(焊盘信息)。

如果只是做PCB板而不需要一起焊接元件的话,这一步骤的成本是很低的,因为现在(2022年初),大部分PCB厂都提供了低价或免费打样的服务,比如嘉立创、捷配、华秋等,官网就提供在线下单的选项。需要注意的是,不同的制作工艺有不同的价格和制造周期,比如二层板1-2天出货,而四层板要4-5天;加急的话需要额外加钱。我用的是第二个,因为看了一圈只有他家无铅工艺是免费的 XD

七 电路板生产与焊接

给SMT厂(元器件贴片)一般需要准备如下文件:BOM(元器件物料)、GTP(钢网层,用于刷焊锡膏)、PickPlace(焊盘信息)、Assembly Drawing(装配图)。

丁 软件开发的具体步骤

由于我使用的芯片是STM32F103系列,所以使用了STM32CubeIDE作为开发环境。在这一点上,ST做的还是挺好的,将绝大部分硬件访问封装成库,还提供了图形化界面帮助用户配置多用途针脚。STM32CubeIDE是基于Eclipse的二次开发产品,相信稍微偏软件一点的人用起来都是有手就行。

当然,其他的开发环境,比如Keil、IAR等等都是没有问题的,可以用STM32CubeMX生成项目框架后再导入。只不过我图偷懒省事,直接用了他自家的配套产品=w=

一 项目创建

由于嵌入式开发具有硬件依赖性,因而需要在创建项目的时候就指定好主控芯片的型号,尤以核心架构、封装类型为主。在STM32CubeIDE中,可以直接通过图形化界面搜索、选择所需要的MCU型号。

二 引脚功能配置

STM32CubeIDE内置了STM32CubeMX,因而相同地使用.ioc文件完成对主控引脚功能的配置。不过该IDE还提供了非常贴心的保存后自动生成代码的功能,用起来手感不错。不过有一点要非常注意:生成的代码文件里的注释,只有特定注释区间内的代码会在更新配置时保留,写错了地方的代码直接就被删掉了,最好做个备份。

三 代码编写

可以说是再常规不过的C/C++代码编写过程,绝大部分标准库可以正常使用。调用硬件的话,不需要再像传统方法一样自己手动去找寄存器映射的内存地址,直接使用HAL_开头的库方法即可,比如GPIO的HAL_GPIO_WritePin、UART的HAL_UART_Transmit、经典延迟函数HAL_Delay等等。

四 编译、烧录与运行

IDE内的编译操作向来是十分简便的,轻点一下Build Project等待结果出现即可。在STM32CubeIDE中,默认布局在右下角还会展示ROM/RAM的使用情况,方便开发者了解自己编写的程序究竟占用了多少资源。

编译生成的文件可以有多种格式,如bin、hex,甚至Verilog等,STM32CubeIDE默认生成的是bin格式,如果需要其余格式可以去右键菜单Properties>C/C++ Build>Settings>Tool Settings>MCU Post build outputs里勾选需要的Convert to ...选项,就能生成对应格式的固件文件了。

烧录方式的话,常用的有三种:通用的JTAG、ST家的ST-Link和UART ISP。JTAG因为需要的针脚数太多,一般在小型芯片上用的不多,ST-Link就是ST家对UART做的优化,只需要4根引脚就可完成少些、调试等工作。与需要额外购买硬件的JTAG和ST-Link相比,UART ISP属于ST家芯片的内置功能,通过修改芯片的启动模式,可以使用厂家内置的代码启动,由预置代码通过UART协议为用户将数据写入Flash中。对于一穷二白,买东西不但包邮还得倒贴200的学生来说,我自然使用的是无需额外硬件的UART ISP模式烧录程序了。

UART ISP的大致流程是修改[BOOT1:BOOT0]01,然后通过USART1的RX/TX写入数据。工具的话可以使用一个PC端的USB转串口模块(比如CP2102、CH431A等),然后在PC上用软件写入。我使用的工具是FlyMCU,支持.hex格式的二进制文件写入。写入之前可以使用该软件的“读器件信息”功能检查线是否接对了。

完成烧录之后,将所有的器件连接完成,一个嵌入式系统就算制作完成了。这里要强调的是,如果使用杜邦线搭建原型系统,供电线路的链接一定要慎重加慎重。惨痛的教训是,我因为不小心把外置模块的电源极性接反了,结果把电路板的稳压电路给烧了。。。

由于时间有限、钻研不深,本文叙述可能不是十分准确和全面,权当为各位看官对嵌入式开发提供从整体的角度来了解嵌入式的入门性介绍。欢迎跳进嵌入式的大坑!

鬼知道为什么0202年了还要用这个老古董

嵌入式老师今年不打算用硬件板子,说是会增加学生负担,于是给了一个IDE安装包。

我马上就下载下来了,很快啊。

仔细一看,安装包大小100多M,感觉好厉害,开发环境原来可以这么精简。结果安装界面一打开,一股熟悉的16色风格扑面而来,这才意识到原来是上个世纪的软件,最新版本1.2。安装,破解,一气呵成。

打开后,最直观的感觉就是字小得不行,图标都不带文字说明的,要靠鼠标悬浮去读取按钮的功能。

新建项目,创建C文件,编译运行,遇到了第一个问题:

error starting external process process error code 87 (0x57)

这是兼容性的问题,在右键菜单里调整到兼容模式运行基本可以解决问题。我选的是Windows 98/ Windows Me那项,可以正常工作。

然后回到ARM的入门操作,就遇到了第二个坑,汇编格式。没想到这个编译器还是活在按缩进来决定语义的时代(你是Python吗.jpg),折腾了老半天才整出一段正确的汇编代码。

num     EQU     2            

        AREA    code,code,readonly
        ENTRY

start
        MOV     r0, #0
        MOV     r1, #5
        MOV     r2, #2
        BL      func

stop
        SWI     0x123456

func                      
        CMP     r0, #num
        MOVHS   pc, lr
        ADR     r3, JumpTable 
        LDR     pc, [r3,r0,LSL#2]

JumpTable
        DCD     DoA
        DCD     DoS

DoA
        ADD     r0, r1, r2
        MOV     pc, lr

DoS
        SUB     r0, r1, r2
        MOV     pc,lr
        END     

总结一下,要注意的地方是伪指令不能顶头写,不然会被当成标签,然后就报错。

挖藕,厉害了

================
来自我的Armbian on Rock64(大雾)


第一次在Linux环境下配置中文输入法。为啥呢?因为Fedora已经自带装好了,用服务器也不用打汉字啊

实属懒得回寝室拿电脑的神奇操作

然后看到网上的教程,全都零零碎碎的,从ArchWiki看到博客,好像都没说完整= =

简而言之的话安装包括大致5个部分,fcitx本体、输入法(实现方式)、输入法UI实现、输入法皮肤和设置UI:

sudo apt install fcitx fcitx-libpinyin fcitx-tools fcitx-frontend-gtk3 fcitx-ui-classic fcitx-config-gtk

用Linux也有几个年头了,最长碰见的问题就是,不同的程序对于同一套基础软件有着不同的版本需求,比如Python2/Python3,Java8/Java11,以及各个版本的gcc等等。然而,由于太懒一直没有找到一个好的软件版本管理工具。

可是这次在玩Rock64的时候,被mawk活生生地坑了一把,还顺便学会了update-alternatives这个基本命令= =

起因是Rock64的swap虚拟内存。秉持着内存多大,swap就应该有多大的传统思想,看到我4G内存的Rock64只有1G的swap,心里甚是不爽,于是决定修改配置文件来把swap修改到至少2G以上。

由于编写系统的人不同,初始化系统swap的脚本位置也不同。在Armbian的系统下,使用的swap也是压缩的zram,初始化的脚本位置在/usr/lib/armbian/armbian-zram-config

可以看到其中激活zram作为swap分区的函数activate_zram_swap,截取其中的关键部分如下:

# Load zram module with n instances for swap: one per CPU core, $ZRAM_MAX_DEVICES
# defines the maximum, on modern kernels we overwrite this with 1 and rely on
# max_comp_streams being set to count of CPU cores or $ZRAM_MAX_DEVICES
uname -r | grep -q '^3.' && zram_max_devs=${ZRAM_MAX_DEVICES:=4} || zram_max_devs=1
cpu_cores=$(grep -c '^processor' /proc/cpuinfo | sed 's/^0$/1/')
[[ ${cpu_cores} -gt ${zram_max_devs} ]] && zram_devices=${zram_max_devs} || zram_devices=${cpu_cores}
module_args="$(modinfo zram | awk -F" " '/num_devices/ {print $2}' | cut -f1 -d:)"
[[ -n ${module_args} ]] && modprobe zram ${module_args}=$(( ${zram_devices} + 2 )) || return

# Expose 50% of real memory as swap space by default
zram_percent=${ZRAM_PERCENTAGE:=50}
mem_info=$(LC_ALL=C free -w 2>/dev/null | grep "^Mem" || LC_ALL=C free | grep "^Mem")
memory_total=$(awk '{printf("%d",$2*1024)}' <<<${mem_info})
mem_per_zram_device=$(( ${memory_total} / ${zram_devices} * ${zram_percent} / 100 ))

可以看到,脚本获得系统的内存容量,然后按照预先设置好的比例建立好zram的分区大小。奇怪的是,按照脚本设计,zram大小应该是系统内存的一半实际上只有四分之一。

这是为啥呢?好问题。

在我多次修改swap分区比例,并重启测试之后发现,似乎脚本所识别到的内存容量只占总内存容量的一半。在我手动执行了上面的相关代码后,露出了端倪:awk的数据大小有限制。系统所自带的awk,允许的最大整数为2147483647,使用再大的数输入awk,输出的整数结果都不会超过这个数,而这恰好是一个32位有符号整形的最大值。

在网上冲浪后发现,实际上Debian最小化安装版(听名字应该能发现Armbian是Debian家的吧)中,默认自带的awkmawk,查看版本可以发现这玩意还是1996年11月的,怎么想支持64位数据的可能性都不大= =(ps. 查了一下,amd64指令集的提出是2000年,产品最早出现在2003年)

然后就要感谢大公无私的GNU了。作为awk的后继,GNU组织开发了gawk,在实现awk原有功能的基础上添加了大量插件库(虽然我还没用到过),不必多想,64位数据的问题自然早已解决。

安装完gawk后,实际上系统是把/usr/bin/awk最终重定向到了gawk的可执行文件。根据上文表述可以推测,Debian的非最小化安装版本的默认awk不是mawk,而是gawk。这也是为啥只有在嵌入式设备上才容易发生这类问题的原因了吧= =

为什么说是最终呢?观察/usr/bin/awk的指向可以发现,它并非直接指向/usr/bin/gawk,而是指向了/etc/alternatives/awk。这就引出了本文的后半篇内容,update-alternatives命令。(名字又臭又长的,一度以为是ubuntu用户专属命令

update-alternatives是Linux下的一个标准命令。简单解释来说,就是允许在系统中安装同一个软件包的多个版本,并且根据需求修改默认调用软件包版本的版本。比如在本文前半篇中的场景,一个系统中可能同时安装了mawkgawk,两者的基本功能完全一致,到底使用哪一个awk作为默认的这个工作,就可以通过update-alternatives配置软链接轻松完成。

常用命令:

update-alternatives --get-selections # 查看当前所有存在配置的文件(似乎还可以配置程序库)
update-alternatives --config <name>  # 使用交互方式设置该条目的默认配置;如果留空,对当前系统中存在的所有条目依次进行配置

当我实验室的好兄弟告诉我,那台插满了GPU和硬盘的Inspur NF5288服务器家目录炸了的时候,我的内心是拒绝的= =

起初的表现形式是这样的:在家目录下输入ls,直接提示Input/Output error,没有任何商量的余地。
后来重启了一下之后,情况更加混乱了:由于为了合理规划高速/低俗空间,系统装在了RAID 1的SSD中,而家目录则挂在了RAID 5的HDD上。这导致我们的系统启动正常,但是出现了奇怪的IO错误,推测是fstab试图挂载家目录的时候出了问题,结果顺手把系统给崩了。(emm忘记截图了,总是就是要求用户输入root密码修复系统或者Ctrl+D跳过步骤一类的提示,也不知道我是忘记root密码了还是系统出问题了)

然后就开始推测:可能是分区坏了?
遂插入Ubuntu系统安装盘(为啥不是CentOS?因为手头只有Nvidia的安装盘了),准备fsck修复磁盘。然而操作后发现,同样报出I/O error错误,磁盘修复根本无法运行,盘都读不了。

接下来思考后开始怀疑,这个I/O错误指的是不是系统底层硬件上有问题(磁盘修复工具都无法读取,看来是软件无法完成的工作了),于是想起了服务器上8块硬盘上,原本应该是8个绿灯,而现在有2块亮起了红灯。

是不是RAID控制器能给出什么有用的信息?遂重启开机进入RAID管理界面,果然发现了端倪:SSD组成的RAID 1正常工作,而HDD组成的RAID 5处于Offline(即离线/不可用)状态。查看后发现,其中4块好的HDD处于UG状态(推测是正常工作),而有问题的两块处于Frn-Bad状态。

秉着开机时所有HDD全部为绿灯的事实,抱着企业级的HDD(Seagate ST2000NX0253)不会这么容易损坏的心态,查找了一下有没有解决方案,结果还真有:https://support.huawei.com/enterprise/es/doc/EDOC1000163569/e744d41f/restoring-a-hard-drive-in-frn-bad-state

鬼知道为什么最先找到的是西班牙语版的,但我还是说一句菊花NB好吧

SAS3108的RAID管理界面一般有4~5个选项卡,其中第一个可以通过方向键查看磁盘状态。在不同选项卡之间使用Ctrl+N或者Ctrl+P切换。(其实界面最下方有操作说明)

大致步骤如下(华为文档翻译+copy):

  1. 上下键选择到需要修复的RAID阵列,Ctrl+N切换到PD Mgmt(估计是Physical Disk Management的缩写),上下键选到Frn-Bad状态的磁盘,按F2,在菜单中执行Make unconfigured good选项(强制通知RAID控制器本磁盘无物理损坏),然后磁盘会进入Foreign状态。

  2. 之后管理界面会出现第五个选项卡Foreign View。在这里进行RAID配置的恢复。可以参照这个教程:https://support.huawei.com/enterprise/es/doc/EDOC1000163569?section=j04f。 选择到要恢复配置的磁盘标题,然后F2选择Foreign config > Import,完成配置导入工作。

  3. 接下来回到VD Mgmt(Virtual Disk Management),发现之前处在Foreign状态的两块磁盘已经相应地进入了OnlineRebulding状态,分别表示磁盘已经进入了正常工作状态,或是正在进行修复。此时已经可以重新启动,并且正常进入系统了。

  4. 虽然完成配置导入后已经可以启动系统,直接由于不知道在系统正常工作的情况下RAID磁盘的恢复工作是否进行,为了安全起见,本次采用的方法是在RAID管理界面等待修复完成后,再进入系统。修复进度极其缓慢,花了近5个小时才完成一块磁盘的重建= =

后记

后来寻找问题的原因的时候,发现似乎是因为不支持热插拔造成的。

高级作战记录

学长:你看这服务器这么高级,¥%#*#@@#&@%(伸手欲拔出服务器上的硬盘)
我:学长最好还是别拔吧,万一等下出问题...
学长:这又没啥,你看硬盘摆在外面,不就是支持热插拔的吗
(说罢取下一块)
学长:你看,这不是没事吗
(说罢装了回去)

直到几个小时后,有学弟说服务器坏了用不了之后,事态的严重性才扩散开来

(我:得亏学长只拔了一块,拔多了估计真得凉凉)