介绍8 y: z1 T8 d) h% V1 Y
上小节使用我们自己编译的uboot kernel dtb 成功运行,并且使用nfs挂载了根文件系统,至此我们的开发基础条件已经完善,下面就可以编写我们的应用程序了,选择MP157就是看中了它A7双核加M4内核异构的形态,AP侧运行我们比较耗费算力的应用程序,M4内核运行rtos来处理时效性强的任务,合作分工,能够完成更多有意思的创造。本文将分三部分编写示例程序测试,分别是QT基础程序测试、Contex-M4 rtos应用程序测试和 QT程序控制M4固件程序运行及停止。达到真正意义上的异构产品开发形态。后续只需要完善各部分的功能逻辑即可。
2 J4 N; `" K6 W. `9 Z2 I' v
2 A. z; t1 Q |- t3 j: |; kQT基础程序测试( b* X& L; S: z; K. Z) A [
这部分使用QT写一个测试程序,然后使用交叉编译套件编译以后放到根文件系统中,在开发板上测试是否能够正常运行。
. O H- u7 a7 }% z% [% {QT搭建交叉编译套件参考原子配套资料文档安装即可,新建一个基础工程,放一个pushbutton和toolbutton测试,模拟如下:
4 k5 `0 K. w1 W
5 j, ?1 ~' D; {: j
+ F! o/ x8 b! |( p
' H `4 V; s# U: `$ D
交叉编译以后将生成的test程序放到nfs挂载的根文件系统/home/root目录下:
% K5 a. v8 B( w
. E9 f) `$ Z" c$ ?. z+ J
) @0 l; e! m: x" a) f执行如下命令先关闭原子的桌面服务
. W8 Q8 x) S# `6 `, q% c* c- _
. n8 ~% p2 i! |( x) E, Y7 r0 _- systemctl stop atk-qtapp-start.service
复制代码
5 \% Z; E" _) h在启动我们的test qt程序测试:
* l9 j" q1 g9 D* C0 O F8 G- S. H3 _% r" m8 s
A5 f+ R: b( m) Z, R5 W开发板实际测试图:, a) c; h2 I+ ~' h7 d
- P( O6 p7 ]6 O. [
9 \, ], }0 X4 u* e0 P% t. H# n3 V5 j/ A- n9 B' [8 I# l( ]6 ~
QT程序测试正常。" M$ ]. M% D [& S! @* |: x# V1 g9 o W
" v6 n8 k& P1 G+ y( Q7 R1 GM4 rtos应用程序测试4 |1 S, R) H1 Z8 Q1 @2 h/ Q/ [
下面编写M4的rtos应用测试程序控制开发板的LED灯,该led连接到PIO接口,打开stm32cubeide软件,配置clk、gpio、freertos组件等:4 d8 `! L7 W& t+ X, X
clk:
" S8 x) ~" T$ X2 q: o
8 P9 F* n" x6 ]7 Y
$ W( a/ C @, R& Z
* u/ N5 t; {% B) e; r. u- n
5 J* r9 o; X2 D8 s( g8 M9 u
5 X0 B+ G; a7 R8 [3 V4 Y; t! _gpio:6 Y8 {* i( ]0 E6 V7 u4 V! Q+ |
# }- C# N- b! d* @5 C
9 {3 G" e' r: X5 N/ G8 B, O6 r
' Z% D; |, F8 S5 g5 H, C
freertos:7 n" \ G; T7 F) N/ v3 _ @
- _+ Y" X* X8 }; Y) a1 Q
& O1 E7 \- g; H3 e6 x" E- q* |
/ F/ a5 z$ u, H8 m9 e5 _这些配置完成以后基本的freertos就能跑起来了,接下来编写我们的控制函数:
# m" n @8 x# l' Z* n
* P& a+ I5 ]( i
+ J: c) T4 w% ^( n
& q: U: m9 k7 r2 d" z3 r新启一个task,然后在里面调用HAL的gpio控制函数接口进行点灯操作。每一秒翻转一次。编写完成以后编译工程。在工程路径下会生成可执行文件:9 [* {! d* A2 V* J
% X5 z8 W: F5 v7 ?* G* R
& K/ F3 ^5 _3 K1 v w; l4 E6 X6 V9 p2 s, T4 I& l- y
这个就是我们的可执行程序,将m4test_CM4.elf上传到我们的根文件系统/lib/fireware路径下,分别执行如下三条指令即可通过linux加载和暂停M4内核的运行,且观察到LED灯1S变化的动作,rtos应用程序测试成功。
4 O8 F O! M- ` b& k2 e7 e' z; v1 o, c7 R; Z. }* y8 r: O: `
- //加载m4固件程序0 y4 L. K: q1 C; U7 P! `8 y% K' Y
- echo m4test_CM4.elf > /sys/class/remoteproc/remoteproc0/firmware
+ [ @4 R, X5 m- S9 o - //启动m4固件程序
* B( u" k0 C. y8 G- y. Q: W - echo start > /sys/class/remoteproc/remoteproc0/state$ {4 A1 M& g) s# k5 ^" @& \0 K
- //停止m4固件程序
7 ^* ~1 R: E; }$ ]6 g - echo stop > /sys/class/remoteproc/remoteproc0/state
复制代码
' c+ [0 f. `: n. r/ x/ g
) V' K W- Y, @5 I. B. \3 Q
QT程序控制M4固件程序测试
+ `& m9 G2 x8 `( v. i; l% M上一部分其实已经完成了从linux命令行启动M4的rtos应用程序,本部分使用QT程序控制M4rtos的运行和关闭,只用一个pushbotten按钮来控制M4程序的开始和停止。主要程序如下:. c# q- g2 m; E1 f: b, p) f
5 O" U# B( u" d+ o
" @4 F B* E3 K: `- h( M a
# \) U6 Y$ D# P+ _, i- nmainwindow.cpp如下:3 I/ V' B) ]6 o4 l8 `
: s- \0 q( z" X3 k7 X |- #include "mainwindow.h"" y! ?+ K; [/ n! A2 X
- #include <QDebug>
" m( g0 I& N. D - 3 K" O8 ?- t/ Y
- MainWindow::MainWindow(QWidget *parent)+ D8 N( B1 `) F U
- : QMainWindow(parent)
* ]6 l+ D( i- b% x) `4 j - {
9 n0 T* b [" _7 ]0 l - this->resize(800,480);0 n+ }1 m& h0 q# r
- pushbutton = new QPushButton(this);9 F' z; B9 c6 }4 W$ S. ]
- pushbutton->setMinimumSize(200,50);+ |: Z9 Y2 L8 K& _; J W% Z# ~1 ~
- pushbutton->setGeometry(300,215,pushbutton->width(),pushbutton->height());
7 M0 f* f0 d( r8 n- ^ - 0 L, y6 ]: F9 U* J8 g( `* W. m; P6 c: Y
- system("echo none > /sys/class/leds/sys-led/trigger");% V0 I# J# g a! z
- system("cd /lib/firmware");' l9 S& ^8 X6 h* Q4 p- V; e. E
- system("echo m4test_CM4.elf > /sys/class/remoteproc/remoteproc0/firmware");+ P9 j# G8 j9 \) `
- qDebug()<<"load firmware success!"<< endl;" ]: W0 q& F: j% \6 F# t) U
& L% g) _! V: U5 f5 y0 p6 o- connect(pushbutton, SIGNAL(clicked()), this, SLOT(pushButtonClicked()));
$ D% O+ d5 T. D4 K/ K+ K$ \ - pushbutton->setText("Start M4");
( x: V5 {8 G: y - }; h3 O2 q% p: H5 p" P5 K" f/ j
2 {' Y' t3 ^0 t* c& S- MainWindow::~MainWindow()
- y- r) j% r* d3 Y# C - {
& T( D3 {* p- w) B/ V; r - delete pushbutton;
9 F. Y$ u. G4 H- z! _2 n w6 }/ z - }
& U6 X3 `0 d# D8 F# {( p - ) F- G5 Y8 q( ]' h o
- void MainWindow::setM4State()% L0 H2 t6 Z/ O& n( \+ |
- {
7 k" v, D4 d' f6 z; V - bool state = getM4State();
* r) `/ e4 o) ]: H V3 X' { C: v - if(!file.open(QIODevice::ReadWrite))
, b' P* M1 q0 n" S8 h - qDebug()<<file.errorString();
$ @( q; s& G/ d8 q
5 s( Q( ~. Q6 S+ Y- QByteArray buf[2] = {"start", "stop"};, O9 j; p8 D+ K3 N
- if(state), K. L0 x* W o+ i$ L' \( f" `, P
- file.write(buf[1]);
0 v+ M+ G3 |2 ]0 U% r - else% q. P( @8 f( \" U
- file.write(buf[0]);
) v( T% o# M7 L7 b& N7 o0 J - 7 r* W% w; i; F! l7 ]! t7 t2 q
- file.close();
9 O J8 p* C" d8 O4 z9 z$ a; B - }
* Y D: s' \; [% `
% S! } \6 M* r8 z2 q- D5 u) N- bool MainWindow::getM4State() ^5 i* ]3 x" S* R& @+ A+ c' a5 i* p6 ^# n" K
- {3 U6 \' @, W" r h: i8 o
- file.setFileName("/sys/class/remoteproc/remoteproc0/state");4 M. g/ ?- o+ g# V9 N8 q9 Y3 q+ L) \. o
- if(!file.open(QIODevice::ReadWrite))- h2 | r; m7 ~
- qDebug()<<file.errorString();
% r8 n4 W, O; T. X# n) t
1 f, P6 t: s" S1 P4 X _- QTextStream in(&file);# g5 Q8 V. v' M' d4 j
- QString buf = in.readLine();
. n5 y4 D7 _% L - qDebug()<<"state: "<<buf<<endl;
7 C' ^4 D; r" U1 Y; D - file.close();% ~# s2 r E! Z6 W9 X% j% ?
- if(buf == "running"){% m* R0 N. p4 p1 b5 ~
- pushbutton->setText("Start M4");
" N) F# o+ b5 R/ L - return true;
8 P$ _" r$ Q7 N9 @2 d - }else{7 c9 G8 H1 S5 n1 r. [
- pushbutton->setText("Stop M4");+ E% {4 B( h' J: Z
- return false;
# t5 ]% {) t' [! S1 S - }
: b, C7 A2 y8 e5 Y2 F: L% K - }
' @) a* n, Y0 l$ K, O' N - 0 ?0 M9 w( i6 B* s2 I
- void MainWindow::pushButtonClicked()1 _6 v3 c0 [, x$ ?' G/ Z3 ~
- {
1 Y) @5 ~- E) ? - setM4State();
7 Y& I. n9 S n, H# W8 Y' G4 o - }
复制代码 ) c; J2 _) o. J5 T- ~- V2 k
/ [! u( J( L+ Q
测试结果如下:点击屏幕的按钮能够控制M4程序的运行,led灯1S闪烁,再点击一次按钮则程序停止,按钮也会根据运行状态切换显示为Start M4或者Stop M4。1 M9 O& ~, B5 V ~
; i' j: e1 G- A X' v) c* k6 S
7 @2 S( A }: f8 Q% _
" [- S5 ]( `3 A9 \3 Q3 Q" L: I( U- y
本节完毕,下节搞定M4和Linux的通讯问题。3 ^2 r+ k- z- P* z# o: u
————————————————( Q* c0 Y* p: k- D$ n9 B, T% K
版权声明:TNT_TT" M3 Z' V8 V7 c: i) X$ j7 r
2 n# d4 G; [ F% W7 B" J
1 O2 m4 W! r( _# E) j8 ~ |