QEMU模拟mini2440+STM32物联网实验(课程设计)

​基于的demo、演示视频和所需工具包https://pan.baidu.com/s/1hsajcMRga51VgmkntRfl-A?pwd=4z23 提取码:4z23

  • ubuntu16.04
  • arm-linux-gcc 4.4.3
  • QT 4.6.3
  • 项目概览

    本项目旨在实现一个基于Mini2440和STM32之间的通信的物联网实验。Mini2440将充当数据接收端和可视化界面,STM32将模拟传感器数据采集并通过TCP协议发送到Mini2440。Mini2440接收到数据后,将其存储到本地数据库(每条数据记录包含传感器类型、数值和时间戳等信息。),并通过Qt环境进行数据可视化,提供增删改查(CRUD)操作。通过此实验熟悉嵌入式系统的基本开发流程。

    功能需求

    硬件需求

    理论硬件需求:

  • STM32+W5500串口转网口工具(传感器数据采集与上传)
  • Mini2440+显示屏(数据接收、存储与可视化)
    实际上均不需要:
  • STM32采集数据的过程拿DHT11为例,理论上应该是DHT11采集数据,通过IIC通讯传到STM32,STM32通过网线和mini2440连接,通过UDP传输数据到mini2440端。为了节省费用,本实验采集数据的过程用一段C程序模拟,通过UDP通讯发出随机数模拟STM32温度采集
  • mini2440也不需要,在linux下通过仿真工具QEMU对mini2440进行仿真,仿真板可以看作已经部署了linux系统的开发板,但是外围硬件和实际采购板卡有一定的区别(外围电路可以按用户需求进行仿真)
    在实际开发过程中,STM32比较便宜,如果仅有STM32而缺少linux板卡,也可以用STM32实际板卡+QEMU仿真进行实验,通过W5500和计算机进行连接,能够相互ping通
  • 软件部署

  • 虚拟机ubuntu16.04:在windows、linux系统上写的程序用的gcc编译器编译为x86指令集能够在PC端运行,但是PC端和开发板的ARM系统指令集不一样。所谓指令集不一样,就是同一条指令翻译成的机器码在X86上和在ARM上是不一样的。这样就需要做一个转换,linux就有这种交叉编译工具链。这也是需要在ubuntu下开发的原因。

    整体框架图如图:
  • 最终视频演示放到工具包中可自行观看

    环境配置

    QEMU环境配置

    文件准备(工具包->所需工具->needfile.tar.gz)
    QEMU
    tar -xzvf mini2440-18b91f2.tar.gz 解压后目录改名为mini2440-qemu
    路径为:/home/xxx/mini2440/mini2440-qemu
    kernel
    tar -xzvf mini2440-1ebb861.tar.gz 解压后目录改名为mini2440-kernel
    路径为:/home/xxx/mini2440/mini2440-kernel
    U-Boot
    tar -xzvf mini2440-530af20.tar.gz 解压后目录改名为mini2440-uboot
    路径为:/home/xxx/mini2440/mini2440-uboot
    根文件系统
    tar -xzvf rootfs_qtopia_qt4-20100816.tar.gz 解压后目录名为rootfs_qtopia_qt4
    路径为:/home/xxx/mini2440/rootfs_qtopia_qt4
    交叉编译工具链
    tar -xzvf arm-linux-gcc-4.4.3-20100728.tar.gz 解压后目录改名为toolschain
    路径为:/home/xxx/mini2440/toolschain/4.4.3
    文件结构为

    /home/××/mini2440
    ├── mini2440-qemu
    ├── mini2440-uboot
    ├── mini2440-kernel     
    ├── rootfs_qtopia_qt4      
    └── toolschain/4.4.3
    

    编译安装QEMU

    安装QEMU软件,这是一个开发板仿真软件,在linux在对其进行编译安装

    #进入mini2440-qemu文件夹
    #安装依赖库
    sudo apt-get install libsdl1.2-dev	
    #运行脚本配置
    ./configure --target-list=arm-softmmu
    

    出现如下界面,在文件夹下出现makefile,可以进行编译

    #打开Makefile.target修改
    sudo vim Makefile.target     在497行LIBS+=-lz 后加上-lrt
    #编译
    make -j4
    #至此qemu安装成功,/home/***/mini2440-qemu/mini2440是它的文件系统(我的理解,可能有误)
    

    编译安装u-boot

    整个linux由三大部分组成,即bootloader、kernel、file system后两者即内核、跟文件系统,以下依次编译、部署

    #进入mini2440-uboot文件夹
    #编译文件配置
    make mini2440_config 
    #尝试编译
    make -j4
    #报错arm-linux-gcc未找到,arm-linux-gcc路径添加进环境变量
    vim ~/.bashrc              //末尾加下面一行,***是自己的用户名	
    export PATH=$PATH:/home/***/qemu-mini2440/toolschain/bin
    #安装依赖库
    sudo apt-get install lsb-core lib32stdc++6
    #查看工具链
    arm-linux-gcc -v           //显示gcc version 4.4.3
    #尝试编译
    make -j4             //报错
    #结合报错修改相关文件(此时的当前目录为/home/***/qemu-mini2440/mini2440-uboot)
    cd tools/ && vim image.c   //删除369行、1364行等报错函数前的inline前缀
    #common/main.c和include/usb.h也要做一些处理,231行usb_clear_halt前缀去掉
    #编译
    make -j4
    #至此u-boot编译移值完成
    

    编译安装kernel(最容易出错)

    #进入mini2440-kernel文件夹
    #修改makefile
    vim Makefile             //修改如下:183行 ARCH	?= arm   184行 CROSS_COMPILE ?= arm-linux-
    make mini2440_defconfig  //必须执行,用来更新配置文件
    make menuconfig          //如果有报错,安装相关依赖库,直至出现图形配置界面,exit即可
    #编译uImage
    make uImage   
    #注意编译成功显示load address和entry point为30008000,如果是30000000说明是错误的,可能是第一步修改后未执行make mini2440_defconfig
    #至此uImage编译成功         
    

    内核启动

    NFS文件挂载系统准备,NFS用于挂载根文件系统,在linux上能够查看到开发板的文件系统,具体细节可上网查

    #安装nfs服务器
    sudo apt-get install nfs-kernel-server
    #修改配置文件
    sudo vim /etc/exports 
    #末尾添加,***为自己的用户名,注意避免中英文","引起的错误
    /home/***/qemu-mini2440/rootfs_qtopia_qt4  *(rw,sync,no_subtree_check,no_root_squash)
    #保存退出,重启nfs服务器
    sudo /etc/init.d/nfs-kernel-server restart
    #查看文件挂载情况
    showmount -e localhost	//显示/home/***/qemu-mini2440/rootfs_qtopia_qt4  *才对
    

    内核启动文件准备,将之前生成的u-boot.bin和uImage复制到/home/***/mini2440-qemu/mini2440板卡文件夹下

  • u-boot.binmini2440-uboot
  • uImageqemu-kernel下的arch/arm/boot/uImage
  • 此时/home/***/mini2440-qemu/mini2440下应该有如下文件

  • mini2440_nand120.bin
  • qemu-local-img-mount.sh
  • uImage
  • mini2440_start.sh
  • u-boot.bin
  • 针对没有mini2440_nand120.bin文件可参考qemu 模拟-arm-mini2440开发板进行如下配置

    mkdir nand
    sudo mount -t tmpfs none nand/
    dd if=/dev/zero of=nand/nand.bin bs=528 count=127100
    #将生成的nand文件拷贝到mini2440下命名为mini2440_nand128
    

    创建虚拟网口,用来与主机通信,设置到同一网关,虚拟一个网口,安装tunctl
    (以下程序以笔者个人为例)

    sudo apt-get install uml-utilities //创建虚拟网口
    sudo tunctl -u $USER -t tap0
    sudo ifconfig tap0 192.168.183.150 //需要与本机ip地址在同一网段
    #使用ifconfig即可查看tap0虚拟网口创建成功
    本机地址:192.168.183.132
    tap0地址:192.168.183.150
    #使用如下命令,虚拟网口网络方式启动mini2440:
    qemu-system-arm -M mini2440 -serial stdio -mtdblock mini2440_nand128.bin -usbdevice mouse -show-cursor -usbdevice keyboard -kernel uImage -net nic,vlan=0 -net tap,vlan=0,ifname=tap0,script=no,downscript=no
    #报错qemu-system-arm找不到,将mini2440-qemu下的arm-softmmu放在环境变量中
    vim ~/.bashrc                      //最后一行 export PATH=SPATH:/home/***/qemu-mini2440/mini2440-qemu/arm-softmmu
    #启动内核参数设置
    set bootargs noinitrd root=/dev/nfs rw nfsroot=192.168.183.132:/home/msy/qemu-mini2440/rootfs_qtopia_qt4/,proto=tcp,nfsvers=3,nolock ip=192.168.183.140:192.168.183.132::255.255.255.0 console=ttySAC0,115200 mini2440=4tb
    #启动
    bootm
    

    1. 启动mini2440命令中mini2440_nand128.bin参数和上一步的文件名需要一致,额可能为mini2440_nand120.bin
    2. 启动内核后开发板的ip地址为192.168.183.140,最后一个参数mini2440=4tb可以设置启动后屏幕的大小
    3. 如果启动过程中显示屏界面一直加载不出来,卡在小企鹅,是因为权限不够,执行sudo chmod 777 -R /home/msy/qemu-mini2440/rootfs_qtopia_qt4即可
    4. 启动后警告没有操作台unable to open an initial console,进入/home/***/qemu-mini2440/rootfs_qtopia_qt4/dev,执行sudo mknod console c 5 1sudo mknod null c 1 3即可

    最终启动界面如图:

    上述完成了QEMU对mini2440板卡的模拟,在终端执行到界面显示出来后,它和实际的开发板就没区别了,实际开发板有的功能它都可以实现。

    QT环境部署

    所需文件放在工具包->所需工具->QT环境移植下,解压后触摸屏包和qt包均放到/opt目录下,qt包命名为qt-4.6.3-arm-source

    触摸屏驱动编译

    本部分主要参考嵌入式Linux–tslib下载、编译、安装_tslib编译_liefyuan的博客

    #安装相关依赖
    sudo apt-get install automake autoconf libtool libsysfs-dev
    #为configure做准备, 防止编译时出错
    echo  "ac_cv_func_malloc_0_nonnull=yes"  > tmp.cache   //生成一个tmp.cache的文件,里面写的前述""内的内容
    #脚本配置编译所需文件
    sudo ./autogen-clean.sh
    sudo ./autogen.sh
    

    此时如果按照参考博客的正常步骤进行编译安装会报错

    参考宏报错解决方法在 tslib-1.4/config.h 添加如下宏

    #define ABS_MT_SLOT             0x2f    /* MT slot being modified */
    #define ABS_MT_PRESSURE         0x3a    /* Pressure on contact area */
    #define ABS_MT_DISTANCE         0x3b    /* Contact hover distance */
    #define ABS_MT_TOOL_X           0x3c    /* Center X tool position */
    #define ABS_MT_TOOL_Y           0x3d    /* Center Y tool position */
    

    添加后重新配置文件并编译

    #配置,生成makefile
    ./configure --host=arm-linux ac_cv_func_malloc_0_nonnull=yes --cache-file=arm-linux-.cache --prefix=/usr/local/tslib/
    sudo env PATH=$PATH:/home/***/qemu-mini2440/toolschain/
    4.4.3/bin make install
    

    成功后目录/opt/目录下就有了安装好的tslib文件夹了
    验证触摸库在/usr/local/tslib/bin中,运行file ts_calibrate出现如下结果即可

    QT 源码交叉编译

    源码文件在工具包中获取,这部分主要参照下载编译安装运行QT进行配置

    #mkspecs/qws/linux-arm-g++/qmake.conf配置文件修改
    QMAKE_CC=/home/***/qemu-mini2440/toolschain/4.4.3/bin/arm-linux-gcc -lts
    QMAKE_CXX=/home/***/qemu-mini2440/toolschain/4.4.3/bin/arm-linux-g++ -lts
    QMAKE_LINK=/home/***/qemu-mini2440/toolschain/4.4.3/bin/arm-linux-g++ -lts
    QMAKE_LINK_SHLIB=/home/***/qemu-mini2440/toolschain/4.4.3/bin
    /arm-linux-g++ -lts
    # modifications to linux.conf
    QMAKE_AR=/home/***/qemu-mini2440/toolschain/4.4.3/bin/arm-linux-ar cqs
    QMAKE_OBJCOPY=/home/***/qemu-mini2440/toolschain/4.4.3
    /bin/arm-linux-objcopy
    QMAKE_STRIP=/home/***/qemu-mini2440/toolschain/4.4.3/bin/arm-linux-strip
    
    #脚本文件准备,源码文件夹下新建config.sh脚本文件
    #!/bin/sh
    ./../qt-4.6.3-arm/configure \
    	-opensource \
    	-confirm-license \
    	-release \
    	-shared \
    	-fast \
    	-embedded arm \
    	-xplatform qws/linux-arm-g++ \
    	-no-3dnow \
    	-no-libmng \
    	-no-opengl \
    	-no-openssl \
    	-no-mmx \
    	-no-sse \
    	-no-qvfb \
    	-no-glib \
    -no-webkit \
    	-no-phonon \
    	-no-neon \
    	-qt-mouse-tslib \
    	-qt-libjpeg \
    	-qt-libpng \
    	-qt-zlib \
    	-little-endian \
    	-depths 16,18,24 \
    	-I/usr/local/tslib/include \
    	-L/usr/local/tslib/lib \
    	-prefix /opt/qt-4.6.3-mini2440
    
    #运行脚本
    sudo chmod a+x config.sh
    ./config.sh
    #编译、安装
    make -j4
    sudo make install
    

    说明: 配置脚本文件用到了触摸文件。编译完成后,QT库在/opt/qt-4.6.3-mini2440下。

    移植

    目的:将编译好的触摸库和QT库(目前还存在于linux系统下)移植到开发板文件系统中,在共享根文件系统(home/***/qemu-mini2440/rootfs_qtopia_qt4)下/usr下新建/lib,然后做如下操作:

  • 将linux系统中/opt/qt-4.6.3-mini2440/lib(编译好的qt库)和/usr/local/ tslib/lib(编译好的触摸屏库)放到上述共享根文件系统的/usr/lib文件夹下
  • 将qt源码文件夹下即/opt/qt-4.6.3-mini2440/lib/fonts放到挂载文件夹的/usr/lib下
  • 在开发板中加入环境变量,这里要注意,挂载目录home/***/qemu-mini2440/rootfs_qtopia_qt4在linux看来是这个路径,而开发板启动后在开发板看这个路径就是根目录/,因此在次共享根文件系统下的etc/profile下加上如下环境变量下面分别是错误和正确示范,这时开发板在运行时就能够找到相关的QT库了
  • #错误的如下
    #export QT_ROOT=/home/msy/qemu-mini2440/rootfs_qtopia_qt4/usr
    #export LD_LIBRARY_PATH=SQT_ROOT/lib
    #export QT_QWS_FONTDIR=SQT_ROOT/Lib/fonts
    #正确的如下
    export LD_LIBRARY_PATH=/usr/lib
    export QT_QWS_FONTDIR=/usr/lib/fonts
    

    QT开发工具准备

    本小节用到的工具笔者没备份,在工具包中没有,需要大家自行下载哦!

    PC端QT编译

    本章节包括tslib和QT的交叉编译,编译出的文件供开发板使用,也就是说写好的程序通过交叉编译放到开发板上可以运行。有个问题是,正常的开发流程是:
    写好程序->在PC上调试运行->运行结果无误->交叉编译代码->放到板卡文件系统中->板卡上运行因此正常情况下在ARM系统下的工具在PC端也要有,便于调试。QT的源码编译需要用gcc工具编译到PC端供PC端使用,此处笔者用的PC编译工具为gcc-4.4.7编译QT源码。这个工具可以自行下载,然后在编译的时候指定gcc为这个版本即可。笔者安装在/opt/qt-4.6.3-pc(新建)下。

    QTCreator下载

    QTCreator对于QT来说相当于VSCode之于C/C++,pycharm至于python,是针对QT的一个代码编辑器。笔者选择的 QTCreator版本为qt create4.6.2。可以用QTCreator写好代码后,在终端进行编译,使用不同的工具编译(gcc)或交叉编译(arm-linux-gcc)。
    为了更方便,读者可以稍加配置,可以直接在QTCreator选择编译or交叉编译,根据选择QTCreator能够在不同文件夹下生成可执行代码,最终的效果如图:在界面上选择编译器,选择好之后编译就行,不同编译器生成的可执行文件在不同文件夹。

    要达到上述目的,按照如下进行配置:

  • 配置PC编译环境:Kits->编译器设置成x86-gcc,版本设置为上述版本名字,编译器路径在/opt/qt-4.6.3-pc/bin/qmake。
  • 配置交叉编译环境:Kits->编译器设置成arm-linux-gcc,版本设置为上述版本名字,编译器路径在/opt/qt-4.6.3-mini2440/bin/qmake

    :QT每次需要换编译工具链重新编译需要先删除.pro.user然后再编译,才能正确得到正确的文件。不同工具编译的文件会存放到如下图所示的两个文件夹内
  • 数据库环境部署

    交叉编译

    需要完成下述任务:PC端不再赘述

  • PC编译工具链编译数据库源码,保证数据库在PC端能够运行,便于测试开发。
  • 交叉编译编译数据库源码,得到数据库文件,部署到嵌入式系统中,配置好数据库运行的嵌入式环境。
    源码准备,将解压出来的包命名为Sql-arm,在Sql-arm下新建bulid文件夹

    交叉编译数据库环境参考嵌入式数据库sqlite在2440上的移植按如下进行:
  • #配置编译文件
    sudo ./configure --prefix /home/***/Sqlite/Sql-arm/bulid/target
    #编译
    sudo env PATH=$PATH:/home/***/qemu-mini2440/toolschain
    /4.4.3/bin ./configure --prefix /home/***/Sqlite/Sql-arm/bulid/target --host=arm-linuxsudo env PATH=$PATH:
    /home/***/qemu-mini2440/toolschain/4.4.3/bin make install
    

    安装好后进入/home/***/Sqlite/Sql-arm/bulid/target可以看到如下文件,此处进入bin文件夹查看里边文件性质file sqlite3ARM说明无误。

    移植

    将上面文件分别移植到挂载目录(/home/msy/qemu-mini2440/rootfs_qtopia_qt4/)下的/usr/bin/usr/include/usr/lib下并打开挂载目录/etc/profile新增开发板环境变量

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib
    export QT_QWS_FONTDIR=/usr/lib/fonts
    export QT_PLUGIN_PATH=/home/plg/plugins
    export PATH=$PATH:/usr/include
    

    测试

    上述过程完成后,一切顺利的话开发板有了数据库环境,可以将开发板运行起来后按下图进行测试,都是一些数据库操作的语法,能够起作用说明数据库环境配置成功。

    也可以采用demo程序进行测试,测试数据库的一些接口是否正常

    #include <stdio.h>
    #include <sqlite3.h>
    
    int main(int argc, char* argv[])
    {
       sqlite3 *db;
       char *zErrMsg = 0;
       int rc;
       rc = sqlite3_open("test.db", &db);
       if( rc ){
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
       }else{
        fprintf(stderr, "Opened database successfully\n");
       }
       sqlite3_close(db);
    }
    

    上述程序用arm-linux-gcc进行编译,放到挂载的目录下运行,结果如下:

    应用开发

    应用开发准备

    1. Ubuntu和mini2440网络互通,通过ubuntu去pingQEMU看能否ping通,能ping通说明没问题,不用在意开发板端能不能ping通ubuntu
    #关闭防火墙
    sudo ufw disable
    #ubuntu ping 开发板
    ping 192.168.183.140
    #有数据反馈说明网络是通的
    

    以太网通信、数据库存储

    demo程序在工具包->应用程序开发->以太网+数据库中

  • STM32作为客户端采集数据,将采集到的数据通过以太网通信发给服务器,编译为pc代码在linux下运行,对应程序为Client.c
  • mini2440作为服务器接受客户端的数据,将保存的数据存到数据库中,交叉编译为arm代码在嵌入式板卡上运行,对应程序Server.c
  • Makefile代码比较短,它的目的是将客户端程序编译为x86架构,服务器程序编译为ARM架构,如下:
  • CROSS=arm-linux-
    all: server-talk client-talk
    server-talk:
        $(CROSS)gcc -o server-talk server.c -lsqlite3 -I /home/msy/Sqlite/Sql-arm/bulid/target/include -L/home/msy/Sqlite/Sql-arm/bulid/target/lib
    client-talk:
        gcc -o client-talk client.c -lsqlite3 -I /home/msy/Sqlite/Sql/bulid/target/include -L/home/msy/Sqlite/Sql/bulid/target/lib
    clean:
        @rm -vf *talk *.o *~
    

    笔者将客户端程序和服务器程序均放在/home/msy/qemu-mini2440/rootfs_qtopia_qt4/home/plg下,运行makefile在此目录下会生成两个可执行文件,在linux下运行客户端程序;利用qemu登录mini2440出现操作台后进入/home/plg文件夹运行服务器程序,可得到如下所示的结果:

    笔者进行数据发送、接收的过程中,对于数据的发送、接收、数据库存储写过程序(这个最终程序是在它的基础上演变来的),当时的程序现象如下(仅供参考),当时的程序还是手动输入数据进行发送、接收。

    QT-UI设计

    采用QT进行数据库的可视化,并实现QT对数据库的增、删、改、查、报表输出的功能。主要运用QLabelView、button、Label组件对UI界面进行设计。QLabelView对数据库进行可视化,button组件配合相关的槽函数完成增、删、改、查、报表输出的功能。采用QT提供的数据库接口函数对槽函数进行代码相关书写。
    值得说明的是widget.cpp下的两行程序:

        //db.setDatabaseName("/home/msy/qemu-mini2440/rootfs_qtopia_qt4/home/plg/TEMP.db");
        db.setDatabaseName("/home/plg/TEMP.db");
    

    这两行代码是供调试过程中选择的。前面也做了说明,为了调试代码,经常在pc机上编译、运行、调试好后再进行交叉编译放到嵌入式板卡运行。//db.setDatabaseName("/home/msy/qemu-mini2440/rootfs_qtopia_qt4/home/plg/TEMP.db");就是在pc调试的时候数据库的路径,当时笔者在调试的时候将服务器的程序也编译为x86架构在pc端对整个流程进行测试,此时客户端、服务器程序均在pc端的/home/msy/qemu-mini2440/rootfs_qtopia_qt4/home/plg文件夹下运行,此时数据库的路径就是在这个路径下。调试完毕后放到板卡上,对于板卡来说,他看到的数据库路径自然是在/home/plg/TEMP.db下。读者在pc调试和正常板卡运行时根据需要做出选择即可。
    最后的程序运行效果及整体流程效果可见工具包包含的录制视频。

    可扩展性

    1. 应用开发可结合实物及具体传感器做数据采集,此时传感器可涉及更多的板内通讯协议,比如基于IIC通讯的温湿度传感器
    2. 以太网通讯可以使用物联网常用的MQTT协议,此时STM32端将W5500串口转以太网换成ESP8266串口蓝牙模块即可
    3. 结合实物及进行以太网通信时,需要板卡、宿主机、虚拟机三者相互ping通,一般需要对虚拟机进行网络配置,配置一个NAT网卡和一个桥接网卡,一方面保证虚拟机能够上网,另一方面可以保证和实际STM32能够ping通

    上述环境及代码笔者均能够跑通没问题,鉴于笔者能力有限以及linux系统的bug总是不经意间出现,希望不要给大家造成困扰,有问题很乐意和大家进行讨论!!!对于一些软件包笔者未留存的,笔者也没有再行下载,请大家见谅,自行查找一下哈!
    对于文中有诸多借鉴之处有疏忽的地方希望不要给原创作者造成不必要的困扰,我不会有恶意哈,感谢为这个知识体系大厦付出过的前辈们!!!
    笔者是一个毕业即将就业的学生,写博客的初衷是为了分享自己做的一些东西也希望帮助一些一样研究方向的人少走一些不必要的弯路,也欢迎大家对笔者进行指导,大家一起进步,不胜感激!!!

    作者:小阳阳mcy

    物联沃分享整理
    物联沃-IOTWORD物联网 » QEMU模拟mini2440+STM32物联网实验(课程设计)

    发表回复