编译可执行文件在海思3516开发板运行并加入开机启动中

一、编译可执行程序并导入海思开发板运行测试

在ubuntu系统中执行行make编译,其中Makefile中用海思开发板编译工具arm-himix200-linux-gcc对源文件进行编译:
注意!根据源文件语言类型选择gcc还是g++,如果选错,虽然能编译成功但可能无法正确执行!

打开MobaXterm软件
用网线连接海思开发板,选择SSH模式(因为SSH模式相比Telnet功能更强大,可以传输文件)
输入开发板IP 192.168.1.120  用户名root  密码hisi123 并连接,成功后如下图

 

将编译好的可执行文件(本例为main_hi.exe)拖拽到上图左侧希望的目录中。

用cd命令,进入可执行文件main_hi所在目录,运行 chmod 777 main_hi 提升其执行权限

提升权限后,用ls -l命令查看main_hi所在目录,发现main_hi变成了绿色,如下图所示:

开发板插入相机,用lsusb查看是否识别到VID,PID

用 ls /dev命令查看dev文件夹中是否识别到了Video0

运行./main_hi 可执行文件,看是否正常执行。未能执行的话排查处理问题直至可以执行。
**************************************************************************************************************

二、如何将可执行文件移植到开机启动项中

根目录下,etc/init.d里的文件,将在开发板开机后按照Sxx序号从小到大依次执行。因此只需要在这些文件中添加我们想要执行的命令脚本。

将编译好的可执行文件main_hi放入/mnt文件夹中,并运行chmod 777 main_hi 提升其执行权限。 

用vi S01udev命令,打开S01udev文件,按“i”进入编辑模式,移动光标到原程式末端,添加如下脚本内容:【Linux系统启动文件中加sleep延时】

在S01udev中添加的脚本内容如下所示:

也可以用#添加备注或用echo打印信息,如下图所示:

添加完成后,按ESC键退出编辑模式(注意:此时虽退出编辑状态,但并未退出该文件,页面并未变化)

按shitf+:输入:然后输入wq并回车,即输入:wq命令,保存并退出该文件,返回到命令窗口中。如果不保存文件退出,则输入:q

然后按开发板复位按钮重新启动系统,可以看到刚加入启动过程的程序main_hi正常调用500帧的帧频时间并运行打印,如下图:

如果添加了打印信息,则启动时出现打印信息,如下图:

附,相关知识点:

一、延时函数的两种常用名称是sleep和delay。

一般在上位机多见sleep,单片机常用delay。那么sleep和delay的意义有何区别?
sleep意为睡眠,即线程挂起,由定时器重新唤醒线程。sleep作用期间,该线程不占用CPU资源。
delay意为延迟,即线程等待,由线程自身进行循环查询,在设定时间之后退出循环。delay作用期间,该线程占用CPU资源。

在上位机,delay常可以和sleep组合使用,即循环查询中调用sleep,降低CPU占用率。sleep是由系统内核、固件库或特殊功能寄存器提供调用接口,而delay是程序员可以完全自己定义的一个循环函数,没有标准。sleep是由硬件提供的延时,如果要中断sleep,也需要通过相关的特殊功能寄存器进行操作。delay是软件提供的延时,可以使用任意内存空间作为信号使delay退出循环。
另外,wait和sleep具有相同的含义,都是由硬件提供的延时,但wait比sleep具有更多的功能。wait常用来表示可中断的延时。而sleep常用来表示不可中断的延时。Java中还有一个叫await的函数。由于Java中wait是Object的成员函数,Lock中只能换用一个近义词await。
关于wait的唤醒,Qt中是叫wakeOne和wakeAll,Java中是叫notify和notifyAll,Java中的await对应的唤醒函数是signal和signalAll。唤醒函数的命名似乎没有什么规律。一些脚本语言中的sleep和wait并没有对应的唤醒函数,而是使用键盘上的任意键唤醒。

linuxshell中引号的作用:Linux Shell - 单引号 ( ‘ )、双引号 ( “ ) 和反引号 ( ` )_单引号符号-CSDN博客

Linux系统中,可以通过延时启动命令来延迟启动某个服务或应用程序。延时启动命令可以在系统启动之后一段时间才开始执行,有助于避免启动时的资源竞争和冲突。以下是几种常用的Linux延时启动命令:

1. sleep命令:sleep命令可以使系统暂停指定的时间间隔后再执行后续命令。可以通过以下命令在启动或者脚本中添加延时:
   sleep 10
   上述命令将会延迟10秒后再执行后续命令。可以根据实际需求调整时间间隔。
   在bash脚本中使用sleep命令可以让脚本暂停执行一段时间。语法如下:
   sleep [时间]
   其中,时间的单位可以是秒(s)、分钟(m)、小时(h)或天(d)。例如,睡眠5秒可以这样写: sleep 5s
   或者使用分钟单位: sleep 1m

2. at命令:at命令可以在指定的时间执行后续命令。通过at命令的搭配使用,可以实现延时启动。以下是使用at命令延时启动的 
    示例  echo “command” | at now + 10 minutes
    上述命令将在当前时间的10分钟后执行后续命令。
    使用at指定运行时间: at [时间]  
    时间的格式可以是HH:MM,也可以是明天或以后的某一天。例如: at 15:303. systemd timers:systemd timers是一种用于定时触发的服务单元,可以通过systemd timers实现服务的延时启动。在        
   systemd中创建一个timer单元文件,指定延时启动的时间间隔和执行的命令即可。示例命令如下:(注释:反引号 ` 括起来的命令又被双引号 ( " ) 括起来,则命令会执行。)
 

   sudo nano /etc/systemd/system/mytimer.timer

   “`  
   [Unit]
   Description=My Timer

   [Timer]
   OnBootSec=10min
   OnUnitActiveSec=1d
   Unit=mytimer.service

   [Install]
   WantedBy=multi-user.target
   “`

   sudo nano /etc/systemd/system/mytimer.service

   “`
   [Unit]
   Description=My Service

   [Service]
   ExecStart=/path/to/command

   [Install]
   WantedBy=multi-user.target
   “`

   上述命令将在系统启动后的10分钟执行指定路径的命令。


4. systemd命令:对于使用systemd进行服务管理的系统,可以使用systemd的`systemctl`命令来延时启动服务。可以使用`systemd-analyze`命令来确认启动时间。操作步骤如下:

   1)找到你想延时启动的服务的unit文件,一般位于`/etc/systemd/system`目录或者`/usr/lib/systemd/system`目录中。

   2)编辑该unit文件,添加`ExecStartPre`行并指定延时启动的命令。例如:
   “` ExecStartPre=/bin/sleep 10s  “`

   3)保存并退出编辑器。

   4)重新加载systemd配置文件:
   “`  sudo systemctl daemon-reload  “`

   5)重启服务:
   “`  sudo systemctl restart [服务名]  “`

   现在该服务将在延时时间后启动。5. cron定时任务:cron是一个Linux系统中的定时任务管理工具,可以通过cron实现延时启动的功能。通过编辑cron配置文件,指定延时启动的时间和执行的命令即可。 
    示例命令如下:

    crontab -e

   “`
   # 延时10分钟启动command
   @reboot sleep 10m && /path/to/command
   “`

   上述命令将在系统启动后的10分钟执行指定路径的命令。

6. screen命令:screen命令是一个会话管理工具,可以在终端中创建多个会话,并通过后台运行的方式执行命令。通过在screen会话中执行延时启动的命令,可以实现延时启动的效果。示例命令如下:

   screen -dmS sessionname bash -c ‘sleep 10m && /path/to/command’

   上述命令将在后台创建一个名为sessionname的screen会话,并在会话中执行延时启动的命令。

以上是Linux系统中常用的延时启动命令,用于不同的场景和目的。`sleep`命令适用于一般的延时需求,`at`命令适用于一次性计划任务,而`systemd`命令适用于服务的延时启动。可以根据自己的需求选择合适的命令来延时启动。
 

二、init.d文件夹简单说明

  /etc/init.d 是 /etc/rc.d/init.d 的软链接(soft link)。可以通过 ll 命令查看。

ls -ld /etc/init.d
lrwxrwxrwx. 1 root root 11 Aug 30 2015 /etc/init.d -> rc.d/init.d
  都是用来放服务脚本的,当Linux启动时,会寻找这些目录中的服务脚本,并根据脚本的run level确定不同的启动级别。

  在制作服务脚本的过程中,使用了Linux的两个版本,CentOS和Ubuntu,需要在两个版本中都可以开机启动服务。但Ubuntu没有 /etc/rc.d/init.d这个目录,所以,为了保持同一种服务在CentOS和Ubuntu使用的统一性,将服务脚本(注:服务脚本在两个不同版本中是不同的)都放在 /etc/init.d 目录下,最终达到的效果是相同的。

  需要说明的是:在CentOS和Ubuntu两个版本中,除了服务脚本放置的目录是相同的,服务脚本的编写及服务配置都是不同的。比如CentOS使用Chkconfig进行配置,而Ubuntu使用sysv-rc-conf进行配置。

三、 系统启动过程

  1)BIOS自检 ,BIOS的功能由两部分组成,分别是POST码和Runtime服务。POST阶段完成后它将从存储器中被清除,而Runtime服务会被一直保留,用于目标操作系统的启动。BIOS两个阶段所做的详细工作如下:

  步骤1:上电自检POST(Power-on self test),主要负责检测系统外围关键设备(如:CPU、内存、显卡、I/O、键盘鼠标等)是否正常。例如,最常见的是内存松动的情况,BIOS自检阶段会报错,系统就无法启动起来;

  步骤2:步骤1成功后,便会执行一段小程序用来枚举本地设备并对其初始化。这一步主要是根据我们在BIOS中设置的系统启动顺序来搜索用于启动系统的驱动器,如硬盘、光盘、U盘、软盘和网络等。我们以硬盘启动为例,BIOS此时去读取硬盘驱动器的第一个扇区(MBR,512字节),然后执行里面的代码。实际上这里BIOS并不关心启动设备第一个扇区中是什么内容,它只是负责读取该扇区内容、并执行。

  至此,BIOS的任务就完成了,此后将系统启动的控制权移交到MBR部分的代码。

  2)系统引导,通常情况下,诸如lilo、grub这些常见的引导程序都直接安装在MBR中。详细过程,请自行google

  3)启动内核,它首先会去解析grub的配置文件/boot/grub/grub.conf,然后加载内核镜像到内存中,并将控制权转交给内核。而内核会立即初始化系统中各设备并做相关的配置工作,其中包括CPU、I/O、存储设备等。

  关于Linux的设备驱动程序的加载,有一部分驱动程序直接被编译进内核镜像中,另一部分驱动程序则是以模块的形式放在initrd(ramdisk)中。

   Linux内核需要适应多种不同的硬件架构,但是将所有的硬件驱动编入内核又是不实际的,而且内核也不可能每新出一种硬件结构,就将该硬件的设备驱动写入内核。实际上Linux的内核镜像仅是包含了基本的硬件驱动,在系统安装过程中会检测系统硬件信息,根据安装信息和系统硬件信息将一部分设备驱动写入 initrd 。这样在以后启动系统时,一部分设备驱动就放在initrd中来加载。这里有必要给大家再多介绍一下initrd这个东东:

   initrd 的英文含义是 bootloader initialized RAM disk,就是由 boot loader 初始化的内存盘。在 linu2.6内核启动前,boot loader 会将存储介质中的 initrd 文件加载到内存,内核启动时会在访问真正的根文件系统前先访问该内存中的 initrd 文件系统。在 boot loader 配置了 initrd 的情况下,内核启动被分成了两个阶段,第一阶段先执行 initrd 文件系统中的init,完成加载驱动模块等任务,第二阶段才会执行真正的根文件系统中的 /sbin/init 进程。

  通过以上分析,grub的stage2将initrd加载到内存里,让后将其中的内容释放到内容中,内核便去执行initrd中的init脚本,这时内核将控制权交给了init文件处理。我们简单浏览一下init脚本的内容,发现它也主要是加载各种存储介质相关的设备驱动程序。当所需的驱动程序加载完后,会创建一个根设备,然后将根文件系统rootfs以只读的方式挂载。这一步结束后,释放未使用的内存,转换到真正的根文件系统上面去,同时运行/sbin/init程序,执行系统的1号进程。此后系统的控制权就全权交给/sbin/init进程了。

  初始化系统,接下来就是初始化系统的工作了,/sbin/init进程是系统其他所有进程的父进程,当它接管了系统的控制权先之后,它首先会去读取/etc/inittab文件来执行相应的脚本进行系统初始化,如设置键盘、字体,装载模块,设置网络等。主要包括以下工作:

  (1)执行系统初始化脚本(/etc/rc.d/rc.sysinit),对系统进行基本的配置,以读写方式挂载根文件系统及其它文件系统,到此系统算是基本运行起来了,后面需要进行运行级别的确定及相应服务的启动。

  (2)执行/etc/rc.d/rc脚本。该文件定义了服务启动的顺序是先K后S,而具体的每个运行级别的服务状态是放在/etc/rc.d/rc*.d(*=0~6)目录下,所有的文件均是指向/etc/init.d下相应文件的符号链接。rc.sysinit通过分析/etc/inittab文件来确定系统的启动级别,然后才去执行/etc/rc.d/rc*.d下的文件。
/etc/init.d-> /etc/rc.d/init.d
/etc/rc ->/etc/rc.d/rc
/etc/rc*.d ->/etc/rc.d/rc*.d
/etc/rc.local-> /etc/rc.d/rc.local
/etc/rc.sysinit-> /etc/rc.d/rc.sysinit

  我们以启动级别3为例来简要说明一下,/etc/rc.d/rc3.d目录,该目录下的内容全部都是以 S 或 K 开头的链接文件,都链接到"/etc/rc.d/init.d"目录下的各种shell脚本。S表示的是启动时需要start的服务内容,K表示关机时需要关闭的服务内容。/etc/rc.d/rc*.d中的系统服务会在系统后台启动,如果要对某个运行级别中的服务进行更具体的定制,通过chkconfig命令来操作,或者通过setup、ntsys、system-config-services来进行定制。如果我们需要自己增加启动的内容,可以在init.d目录中增加相关的shell脚本,然后在rc*.d目录中建立链接文件指向该shell脚本。这些shell脚本的启动或结束顺序是由S或K字母后面的数字决定,数字越小的脚本越先执行。例如,/etc/rc.d/rc3.d /S01sysstat就比/etc/rc.d/rc3.d /S99local先执行。

  (3)执行用户自定义引导程序/etc/rc.d/rc.local。其实当执行/etc/rc.d/rc3.d/S99local时,它就是在执行/etc/rc.d/rc.local。S99local是指向rc.local的符号链接。就是一般来说,自定义的程序不需要执行上面所说的繁琐的建立shell增加链接文件的步骤,只需要将命令放在rc.local里面就可以了,这个shell脚本就是保留给用户自定义启动内容的。

  (4)完成了系统所有的启动任务后,linux会启动终端或X-Window来等待用户登录。tty1,tty2,tty3...这表示在运行等级1,2,3,4的时候,都会执行"/sbin/mingetty",而且执行了6个,所以linux会有6个纯文本终端,mingetty就是启动终端的命令。除了这6个之外还会执行"/etc/X11/prefdm-nodaemon"这个主要启动X-Window

至此,系统就启动完毕了。接下来就是执行/bin/login程序,进入登录状态

四、 init.d目录包含许多系统各种服务的启动和停止脚本。

/etc/init.d里的shell脚本能够响应start,stop,restart,reload命令来管理某个具体的应用。比如经常看到的命令: /etc/init.d/networking start 这些脚本也可被其他trigger直接激活执行,这些trigger被软连接在/etc/rcN.d/中。这些原理似乎可以用来写daemon程序,让某些程序在开关机时运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值