先叠个甲,如果出现了本指南没有覆盖到的错误,还是需要求助有经验的同学。希望大家作业完成顺利。当然,如果有大佬觉得这篇指南的内容过于幼稚简单,受限于本人水平,还请多多见谅。

下一篇文章指路: THU-2023年春嵌入式课程实验指南——大作业Part2-3

题目要求概述

  • 1、使用系统I/O函数读取WAV音频文件,并将音频文件参数输出至命令行。
  • 2、将上一步读取到的音频文件参数写入开发平台上的txt文件中。
  • 3、实验最终结果为:在开发板中运行目标程序后,会在同目录文件夹下生成一个与音乐文件名同名的txt文件,文件中包含有WAV音频文件的参数。

部署环境简介

  • 硬件环境
    • 电脑系统
      • 本实验中电脑系统为Windows 10、Windows 11和macOS均可顺利运行。
    • 开发板系统
      • 自9字班开始使用的新设备盒,注意开发板的启动模式选择EMMC启动
  • 软件环境
    • xshell版本: Xshell 7(Build 0122)
    • xftp版本: Xftp 7(Build 0119)
    • vmware版本: 16.2.2 build-19200509
    • ubuntu版本: 18.04.6LTS (即课程提供的ubuntu)

实验流程

流程概述

  • 利用Xshell串口工具连接开发板,并在Windows/macOS系统上的VMware中的Ubuntu系统中编写相应程序,通过交叉编译生成目标文件,通过Xftp工具将编译好的程序传输至开发板运行。

实验操作步骤

在实验操作流程当中遇到问题,可以先看下一节中的问题与解决,如果没有覆盖到读者的问题,那读者还需要去咨询有经验的同学。

  • 1、下载开发环境:从课程提供的下载链接(以每年最新链接为准)中下载开发环境(包含有虚拟机镜像、vmware安装程序、xshell安装程序、xftp安装程序)
  • 2、导入虚拟机镜像:由于之前已经下载过 VMware Workstation,这里不再赘述。打开虚拟机,导入压缩包解压后得到的1804文件夹下的虚拟机镜像Ubuntu 1804.vmx,账号与密码均为bkrc
  • 3、安装下载的开发环境文件当中的xshell和xftp工具
  • 4、xshell连接开发板:
    • 使用工具箱里的USB Type-B连接电脑与开发板
    • 打开xshell,新建会话,在弹出的窗口中,协议选择SERIAL,名称随意,随后点击左侧列表中的串口,选择端口号,具体端口号需要到电脑的设备管理器中,找到端口一项,其中可以看到Silicon Labs CP210x USB to UART Bridge(COMX) 这里的X,在不同设备上是不同的,在我们小组的三位同学的电脑上分别为COM5,COM6,COM27.
    • 点击连接即可
    • 这样xshell就相当于开发板linux系统的终端,可以实现在开发板上的文件操作
  • 5、ftp连接
    • 使用工具箱里面的网线连接电脑与开发板
    • 这里需要配置主机和开发板的ip
      • 电脑ip:控制面板->网络和共享中心->更改适配器设置,找到以太网接口,右键属性,在弹出的窗口中,双击Internet 协议版本 4 (TCP/IPv4)。选择使用下面的IP地址,然后输入IP地址192.168.1.2和子网掩码255.255.255.0。点击确定以保存设置。
      • 开发板ip:这部分操作需要在xshell上进行,ifconfig eth0 192.168.1.3 netmask 255.255.255.0,可以用过ifconfig检查ip是否已经成功配置
    • 打开xftp工具,新建会话,名称随意,主机填写开发板的ip地址192.168.1.3,下面用户名写root,点击连接即可
    • 这样xftp就实现了电脑与开发板系统的文件传输连接
  • 6、代码编写:在vmware workstation上的home目录下编写代码,参考助教提供的文件操作函数,函数的伪代码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    //当处理 WAV 文件时,可以通过定义一个结构体来表示 WAV 文件头,这个结构体的成员变量对应着 WAV 文件头中的各个字段,从而可以方便地读取和解析 WAV 文件的信息。
    // int 由uint32_t代替,short 由uint16_t代替,因为在跨平台后有可能不兼容
    struct WAV_HEADER
    {
    char chunk_id[4]; // riff 标志号
    uint32_t chunk_size; // riff长度
    char format[4]; // 格式类型(wav)
    ... // 省略其余信息

    } wav_header;
    int wav_header_size; // 接收wav_header数据结构体的大小

    FILE *fp; // 音乐文件指针变量

    // 通过使用 C 语言的标准库函数 fread,可以从音乐文件中读取文件头的数据,并将其存储到先前定义的 struct WAV_HEADER 结构体的实例 wav_header 中。
    // 随后,通过访问 wav_header 结构体的成员变量,就可以获取 WAV 文件的各种信息,如 RIFF 标志、文件大小、文件格式等,从而进行后续的处理和输出。
    void open_music_file(const char *path_name){
    FILE *fptxt; // 输出文件指针
    char name[100] = "[file name].txt" // 新建的输出文本文档的名称
    // 通过fopen函数打开音乐文件
    fptxt = fopen(name, "w");
    fp = fopen(path_name, "rb");
    // 判断wav文件是否为空,为空则退出
    if(fp == NULL){fclose(fp); fclose(fptxt); exit(1);}
    // 把文件指针定位到文件的开头处
    fseek(fp, 0, SEEK_SET);
    // 读取文件,并解析文件头获取有用信息
    wav_header_size = fread(&wav_header, 1, sizeof(wav_header), fp);

    // 输出读取到的wav文件的信息
    printf("wav文件头结构体大小: %d \n", wav_header_size);
    printf("RIFF标志: \t %c%c%c%c \n", wav_header.chunk_id[0], ...);
    ... // 省略输出wav文件剩余信息

    // 同理,将输出信息写入 [file name].txt
    fprintf(fptxt, "RIFF标志: \t %c%c%c%c \n", wav_header.chunk_id[0], ...);
    ... // 省略写入wav文件剩余信息
    fclose(fptxt);
    }

    // 主函数用来解析命令行参数
    int main(int argc, char *argv [])
    {
    int ret; // 用来获取参数类型
    bool flag = true; // 用来判断是否填入参数
    // 遍历所有参数
    while((ret = getopt(argc,argv,"m:")) != -1){
    flag = false;
    switch(ret){
    case 'm': // 如果是m,则调用 open_music_file 函数
    open_music_file(optarg);
    break;
    default:
    // 说明错误使用了别的参数,print usage然后退出
    print usage
    exit(0);
    }
    }

    if(flag){
    // 说明未使用参数,print usage然后退出
    print usage
    exit(1);
    }
    // 最后关闭文件然后退出
    fclose(fp);
    return 0;
    }
  • 7、代码编译: 在虚拟机中,先通过gcc Music_App -o test.wav本地编译测试test.wav文件,成功实现目标效果后,在home目录下,输入加载交叉编译环境指令source /opt/st/myir/3.1-snapshot/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi,随后编译音乐播放器应用程序$CC Music_App.c -o Music_App生成Music_App(实际执行的指令以助教提供的为准,大作业材料不一定都是代代相传的)
  • 8、目标文件的传输与执行:将文件通过xftp连接到开发板上,在xshell中输入ls可以查看到Music_App,通过chmod 777 Music_App指令赋予Music_App可执行文件权限,随后输入./Music_App -m test.wav运行程序,即完成了该实验。

实验中遇到的问题与解决方法

  • 1、开发环境下载:在下载开发环境的时候,使用多开IDM同时下载六个压缩包文件,会导致下载文件错误,解压后的虚拟机镜像文件不可用。解决方法是删除下载文件,用IDM一个一个重新下载
  • 2、xshell和xftp的安装:安装xshell和xftp的时候,警告需要更新版本,但是更新程序一直无响应,比较抽象。解决方法是去NetSarang Computer的官网上,用学生邮箱申请免费版本,下载后安装即可
  • 3、xshell串口端口: 在选择开发板串口端口号的时候,在电脑的设备管理器中,找到端口一项中无法找到Silicon Labs CP210x USB to UART Bridge(COMX) 。解决方法:上silabs的官网,在软件下载处下载CP210x Universal Windows Driver,解压下载的压缩包,右键.inf文件安装即可,随后即可在电脑的设备管理器中,找到端口一项中的Silicon Labs CP210x USB to UART Bridge(COMX) 在串口端口号中选择对应的COMX即可
  • 4、xshell确认与连接:在xshell创建会话中,配置好串口信息后,点击确认后,没有显示创建的会话。
    • 解决方式1:通过资料的查阅,了解到点击确认后,Xshell将保存用户所做的会话配置更改,但不会立即启动与目标设备的连接。关闭会话配置窗口后,用户可以在 Xshell 的会话管理器中找到刚才创建或修改的会话,双击会话条目或选择会话并点击 “连接” 按钮以建立连接。
    • 解决方式2:在配置好串口信息后,点击连接而不是点击确认可以直接连接上会话
  • 5、xshell与开发板成功连接后,一直显示connected,而没有显示出终端输入的位置,也没有助教上课讲述的几分钟的加载过程。解决方式,助教指出这种现象是正常现象,只需要ctrl+C打断即可进入终端输入。
  • 6、开发板ip的配置:这个地方比较的曲折,一开始通过查阅资料了解到可以将开发板挂在到虚拟机,经过一段尝试没有成功,后改用FTP客户端软件连接开发板文件系统,但是这个时候依旧没有使用网线,而是考虑给开发板和电脑连接手机热点,再进行ip配置,但是经过一段时间的尝试依旧失败,最后阅读ppt了解到需要使用网线连接开发板和电脑,再通过chatgpt查询到window和linux的ip配置,最终成功配置了两边的ip,连接上xftp
  • 7、代码编写中的问题
    • 不了解wav文件的信息如何提取。通过查找相关网站,我们找到了拆解wav文件编码信息的方法,并通过将其定义为结构体的方式,将读入的wav文件的信息逐个对应到该结构体中的各个变量,从而可以正确地解析wav文件头。例如,chunk_idchunk_sizeformat 等成员变量对应着 WAV 文件头中的 RIFF 标志、文件大小、文件格式等字段。
    • 不熟悉c语言中字符串处理的方式
    • 为了在后续开发中处理多个命令行参数,需要使用c语言中的getopt函数和optarg变量来循环解析命令行参数,并根据参数执行相应的操作。
    • 需要用uint32_t代替int,用int16_t代替short,因为在交叉编译时不同数据类型有可能不兼容,导致类型长度不一致,因此选择使用统一的类型。
  • 8、执行程序在开发板上无法运行:这个部分是由于对ppt和项目参考文档的阅读的疏忽,可执行文件传输到开发板上没有赋予可执行文件权限,解决方法是:通过chmod 777 Music_App指令赋予Music_App可执行文件权限。
  • 9、再次连接开发板重启实验时ip分配:当再次重启实验后,此时发现直接点击xftp中上一次会话不能顺利连接上开发板,经过检查主机的以太网ip分配记录是保留的,但是开发板上的ip需要重新配置,此时输入ifconfig eth0 192.168.1.3 netmask 255.255.255.0重新配置开发板ip即可
  • 10、xftp中的无线网冲突:当xftp连接所需的ip都已经分配完毕,会话成功创建,但是显示无法连接到指定ip,这个时候可以检查主机上的无线网是否断开,无线网的连接会与以太网的连接相互冲突,这个时候需要断开无线网,xftp即可顺利连接。
  • 11、打开xshell后再连接网线,此时xshell疑似进入网络传输模式,xftp通过网线无法连接开发板。解决方法:先连接网线,再打开xshell

实验优化

本次进行的实验还有三个可优化的地方,作者自己没有实操过,感兴趣的同学可以自己探索:

  • 1、xftp实现虚拟机与开发板的直连,而不是通过windows或者macos作为虚拟机和xftp的中介,可以提高xftp的便携程度。
  • 2、在U-Boot中使用UMS 0 MMC 1指令挂在开发板到虚拟机,可以实现在同一个虚拟机文件夹下同时操作虚拟机文件与开发板文件,可以减少实验流程,提高文件传输效率
  • 3、在代码编写上:
    • 内存管理:目前的代码使用了结构体来保存文件头信息,如果WAV文件的文件头信息较大,可能会占用较多的内存。可以考虑使用动态内存分配,通过指针来操作文件头信息,从而减少内存占用。
    • 性能优化:目前的代码是按字节读取文件头信息的,可以考虑使用更高效的方式,如按块读取,减少IO操作次数,提高性能。
    • 命令行参数解析:目前的代码使用了简单的命令行参数解析方式,可以考虑使用更强大的命令行参数解析库,如getopt_longargp,以支持更复杂的命令行参数选项和错误处理。