|
1. 前言 玩过Linux的朋友, 是不是对Linux无所不能的串口Shell命令控制台羡慕不已, 要是自己做的STM32F系列低档次的MCU也有这种控制交互能力, 会给调试/维护和配置省下多少麻烦事呀, 比如启动/关闭调试或自检模式, 打印调试信息, 配置系统参数, 传输文件等等, 也有相当多的朋友凭借自己出色的编程能力可以实现这些功能, 这里提出我的这个解决方案, 以作交流. 本平台(xc_shell)具备以下性能特点: 大量主要代码, 和具体硬件无关, 移植性强,代码文件少. 只有在处理用户的输入命令时, 才占用CPU资源, 且代码可裁剪到1KB SRAM和4KB Flash; 用户可以非常灵活的添加按模板编写的命令脚本文件, 自定义扩张能力强. 支持操作系统和非操作系统两种场景应用. 支持Ymodem文件传输协议 支持将Flash的扇区开辟为参数区, 可实现本地/远程升级。 实用Led灯信号管理, 可将65535虚拟信号灯选择输出到1个实体LED灯上, 调试时序和状态非常有用 拥有基础的LED管理, 调试模式设置, 命令帮助指令, 复位指令等基础功能
3 r8 F" @2 V9 ~! d( J3 [) N4 n8 s: Y
$ M' ]! K2 j% Y
功能越多设计会越复杂, 为了解释清楚代码, 先向大家解释一下以上功能的基础实现原理, 并提供一个最小的的源码工程。 0 m! r- J$ [! G8 O
2. xc_shell平台介绍2.1 如何实现硬件无关类比Linux会发现, 设备的硬件接口往往会被虚拟成一个文件(驱动), 而Linux内核完全与硬件系统无任何字节关联, 不同平台驱动不同而已, 故而本xc_shell的串口驱动也采用了相似的思路: 1) 串口驱动用一个结构体描述, 这样只需在xc_shell.c中用指针指向这个TTYx_HANDLE结构体对象就可以将串口(tty)硬件与内核联系在一起, 聪明的朋友可能会想到, 假如我将带网络的开发板按此结构体,虚拟一个TTY对象, 岂不是就可以实现一个网络远程控制台了! 这点确实是可以的! 2) 当然诸如多TTY串口实现接口互换等, 都是一个指针和step2中的注入回调处理交换的问题。 3)用户在使用api_TxdFrame或api_TxdByte时”bsp_ttyX.c“,会驱动具体MCU的串口将数据发送出去, 收到一帧数据后,若用户设置了inj_RcvFrame回调处理方法,则会在中断中执行用户的回调处理。 - <i>/*---------------------*
* o: W+ }1 R: I" N$ F8 V - * 指正函数定义/ {2 n: i; [! A' U4 f1 f
- *----------------------*/</i>
, |8 \/ z+ h6 ` d1 \ @( \" T - typedef void (*pvFunDummy)(void);; O* v7 F1 V; P! z) G
-
. I) Z+ X( f( l L1 ^8 [( a( P - <i>//输入整行,输出逻辑</i>
& W- s- Z$ \* h8 I" q; { - typedef void (*pvFunVoid) (void);+ D5 ]2 P) L( v2 |& s
- typedef void (*pvFunBool) (bool bVal);
) D% T; u, p+ I3 w. x$ m - typedef void (*pvFunChar) (uint8_t cVal);0 w6 `6 K# U" Y* x C* w) {
- typedef void (*pvFunShort)(uint16_t sVal);
& `/ R3 W0 t7 I7 V- j9 j - typedef void (*pvFunWord) (uint32_t wVal);
9 ^9 m8 }) e, I4 p5 H+ J - ! r8 ]* W0 i8 |
- <i>//输入整行,输出逻辑</i>
+ h# q9 C7 Z6 y1 f( g - typedef bool (*pbFunVoid) (void);
* N* g+ R }3 {2 j# l- Z - typedef bool (*pbFunBool) (bool bVal);
& E4 z! ~' z6 f - typedef bool (*pbFunChar) (uint8_t cVal);( z# L. K1 w' U" t d& X7 B
- typedef bool (*pbFunShort)(uint16_t sVal);
& p3 n, H( e. i% x$ n9 X0 X' J - typedef bool (*pbFunWord) (uint32_t wVal);+ X3 z' ]4 ^) C3 n
- / x) i3 ]' b+ c
- <i>//输入整形指针,输出逻辑</i>- [3 l G% \ g7 |
- typedef bool (*pbFun_pVoid) (void * pVoid);
- f* F Y& M; {9 v5 T - typedef bool (*pbFun_pChar) (uint8_t * pStr);7 O+ j# \' t: l% D( O Q% q% V
- typedef bool (*pbFun_pShort)(uint16_t * pShor);
3 C6 o5 [4 d5 c2 A, S - typedef bool (*pbFun_pWord) (uint32_t * pWord);
5 g) b. u! W& x6 E% D3 F -
, D$ p9 y- D5 Y* U, q* @ - <i>//输入数据帧,输出逻辑</i>8 h! A8 R* p+ D
- typedef bool (*pbFun_Buffx)(void * pcBuff, uint16_t len );, e8 U' f6 J- i' T( ^) i6 S8 O+ R
- typedef bool (*pbFun_Bytex)(uint8_t * pcByte, uint16_t len );( _" b8 y' ^4 r* D
- <i>/*---------------------* ( e# J; c( c* n+ z- ]4 E
- * TTYx 句柄结构
: l2 ~2 C- \% Q2 F( F9 m0 G - *----------------------*/</i>% C3 V' M+ h, b0 a/ l
- typedef struct TTYx_HANDLE_STRUCT
" b& v" u1 |3 i7 i% s1 E: b' R1 _ - {9 C! K$ D- h) K% U+ R+ N3 ]
- const char * const name; <i>//驱动器名</i>" @, p+ r: a( T2 }3 R0 v# @
- const uint16_t rxSize; <i>//接收大小</i>, ` A) ^- {/ T
- const uint16_t txSize; <i>//发送大小</i>. ~+ z2 s, x n4 u0 P4 w7 d, V
-
; u2 W* z- v2 \9 u - <i>//------------------------------------------------------</i>
' w- e6 O( m9 r* b- N6 y T - <i>//step1: 用户可用API</i>
8 G2 q$ p' o8 o K* f) t - const pvFunWord init; <i>//初始化.</i>7 j3 C# X; |$ B# A N: F5 k
- const pbFun_Bytex api_TxdFrame; <i>//发送数据帧. (发送帧)</i>: j6 x3 i' P: c
- const pbFunChar api_TxdByte; <i>//发送数据字节</i>) `/ m. M9 n. Z: ~8 a, {3 {7 Y0 z. `
-
+ g6 s6 A, U7 \4 E2 d) C - <i>//------------------------------------------------------</i>
: a* V/ C7 c0 `: s3 q - <i>//step2: 注入回调函数</i>+ d1 O+ k; o% `# Z; |4 g
- pbFun_Bytex inj_RcvFrame; <i>//(ISR)接收数据帧. (接收帧)</i>! h& Y4 F4 i2 r1 X C, i+ Y
- pvFunDummy inj_TxdReady; <i>//(ISR)发送完毕回调</i>
; V2 U! \) `, u6 `% v+ c - 5 N9 Q2 \) G3 v$ q7 g6 ^ D$ X' ]
- <i>//------------------------------------------------------</i>* E% m! p1 ^2 ^$ h
- <i>//step3: 接收回调函数</i>$ @& k: Y; h$ ~. c. W' ~
- struct TTYx_HANDLE_STRUCT * pvNext; <i>//连接到下一个指令 </i>/ h+ s. W: T2 L6 L
- }TTYx_HANDLE;
复制代码 可注入的命令脚本(CLI)实现, p. m6 a* c! b( b; B0 z2 P, q
- 命令CLI也是一个结构体对象:
0 X0 ~% d/ p3 T" u- t( g' b # n e' O# O( S7 `6 L+ q* ~% C
4 _5 o- k( _2 V/ _5 I F, ~6 R* d% e) M" R+ A F$ q6 L& c& @
- <i>/*---------------------* - a, z7 j7 k Y# G. ]/ \% N
- * CLI指令
/ c! E- X) s. B: r Z - *----------------------*/</i>" ?; n" r f! r) f! t* i
- typedef struct
4 s9 H* ?# X' R+ [ - {
' A& V# e- h: E* i: o; h - const char * const pcCmdStr; <i>//指令字符串(只能为小写字母)</i>
- {* z6 W* C" @; X9 F - const char * const pcHelpStr; <i>//指令描述,必须以:"\r\n结束". 比如:"help: Returns a list\r\n".</i>$ i# F6 ]. z% ]0 ?" e
- const pFunHook pxCmdHook; <i>//指向回调函数的指针,处理成功返回真否者返回0;</i>
! s" i5 ~8 k v* h" \% P6 ] - uint8_t ucExpParam; <i>//指令期望的参数个数</i>! I3 j4 V" P2 Z3 b% G' o! W7 G
- const MEDIA_HANDLE *phStorage; <i>//指向存储介质,没有的话填充NULL </i>- s. X* c4 z* I9 P
- }Cmd_Typedef_t;
复制代码 5 z: u: {* g; M5 b9 C& t$ n
各位朋友可能会使用到非常多的自定义CLI命令, 格式诸如这个网卡的命令: - const Cmd_Typedef_t CLI_WizMsg=
- g i* S" ?; e, i+ x1 Y" r X4 ?) E - {6 E0 [. P* U, I/ V% y' }
- <i>//识别关键字</i>
& n$ X/ `# [3 N/ P# }+ J$ f - .pcCmdStr = "wiz",
& d. ^& n1 P9 h8 `" X/ A - <i>//帮助内容</i>: J1 c p# }7 H/ E' R
- .pcHelpStr =
h# R/ y' p7 s) U - "[WIZ contorls]\r\n"
8 [) m) I3 t* O. F: @+ U: c- h( P a - " wiz help\r\n"
. r* @* ], @" _5 x; b - " wiz rd info\r\n"
, S1 K4 e- n& P& G, b. i - " wiz reset\r\n"( L+ A+ y' G7 s
- " wiz wr ip <D0>.<D1>.<D2>.<D3>\r\n"/ X7 g5 \# _8 n f$ H8 `
- " wiz wr mask <D0>.<D1>.<D2>.<D3>\r\n"
- C4 X6 o! ^+ Q6 @8 P! p$ n - " wiz wr way <D0>.<D1>.<D2>.<D3>\r\n"% h1 K/ W7 T$ d6 r: ^
- " wiz wr mac <H0>-<H1>-<H2>-<H3>-<H4>-<H5>\r\n"
% e& F* V! \% i" L7 B - " wiz wr port <udp> <bak> <vol> <pic>\r\n"9 J. e2 X3 r8 p8 z0 Q
- " wiz wr sip <D0>.<D1>.<D2>.<D3> <port>\r\n"
' M! V) |# r3 r1 |3 k1 V - " wiz wr cip <D0>.<D1>.<D2>.<D3> <port>\r\n"
# K8 w. P; e3 e5 T+ F3 d1 E, U, f1 E - " wiz load default\r\n"/ a3 J3 b1 M/ M$ K" j
- "[WIZ Test mode]\r\n"
. K s0 F) r, h x/ N/ H; ^3 D - " wiz loop open\r\n": ]) D: ~" F: @ c0 J& n
- " wiz loop close\r\n"
0 O: K0 m0 y" E' { - "\r\n",
9 e9 j3 I% Q4 m. {& T$ g -
( }2 N- p' d/ \9 G$ X% c# Q) { - <i>//处理函数</i>
]( P" z( {6 t0 I2 F" ^- P5 ^ - .pxCmdHook = &Shell_WIZ_Service, <i>//见实体函数</i>
+ a9 `; X8 A3 `: L7 Z -
4 d9 A9 _6 ?. q3 o - <i>//附带数据</i>
! g( ]! v% K ^ - .ucExpParam = 0,# U$ W) }6 w! X* u& e+ n
-
1 Y8 ]/ T5 ]" E' B: [6 N - #ifdef SHELL_USE_YMODEM 8 {" z$ C' P! a2 T& t$ M; A7 m
- <i>//存储介质</i>
' M0 X8 g9 p& Q$ S+ n! g - .phStorage = NULL,
/ G/ ~# Q" J4 e - #endif
" g) {: K* j' N# Q2 O - };# ~$ I# h9 E/ X5 }# O* J; _; T, y
- <i>/*---------------------*
1 ?# X( Y( B( H" D+ C - * CLI 链表节
' t& O* @, e6 V1 @& Y - *----------------------*/</i> w: R. F% i0 t! r, w
- Cmd_List_t WizList = { &CLI_WizMsg, NULL,}; <i>//Shell指令的头</i>
复制代码 0 Q E7 |7 _ b7 \9 |
如配置IP地址输入“wiz wr ip 192.168.1.250\r\n”则可以了 3. 环境准备
' Y% y0 F/ s1 n5 |$ ?$ a3.1 硬件开发环境- STM32F103系列开发板一块, 带USART1接口。
- USB转串口线一根。0 [; H3 U7 Y& I3 x0 B8 _0 r9 O
0 A I8 D! T, D R/ B1 [" b
3.2 软件开发环境- MDK4.72或以上
- SecureCRT串口超级终端# [+ d2 `; b7 Q
8 a6 d$ f6 f% [/ H) e; y; E3 Z
3.3 软件配置在xc_shell使用“/r/n”作为命令的结束符, 而SecureCRT按下Enter不是输入“/r/n”故而需要按下图设置:此外在《终端》/仿真/高级中选取【本地回显】 4. 代码介绍
* B/ C [+ s7 _! P; F5 A4.1 目录结构□ XC_SHELL
( `% W: Q7 y; C% t7 U- ├──┬── BSP_LIB BSP库,硬件相关驱动代买# `! }, P% x( G/ M# D
- │ ├──── bsp_ledx.c 基础LED驱动
2 E$ x( U/ J" E* F - │ └──── bsp_tty0.c 调试串口驱动
T/ B: P0 n1 B( o2 o - │! M# u8 Q3 C' K* \" p. S
- ├──┬──MDK-ARM 工程文件1 Y5 h+ P! c" Z0 x2 b
- │ └──── Project.uvproj3 l1 j4 O& ?& V7 ^( t }
- │
+ P1 |4 U. K7 ^. ?4 S4 l - ├──┬──SHELL_CFG SHELL配置头文件) H; c. e$ r4 R/ J$ e$ I
- │ └──── user_eval.h
$ ~3 ^ N7 B8 p* \9 Y$ ^ - │
' n/ v# N2 Q2 O. ?7 o - ├──┬──SHELL_CORE SHELL内核文件0 y, D, u/ b* R" \2 M/ u! b& A
- │ ├──── xc_shell.c SHELL内核文件
( g! |0 j. ]; H4 V+ B. v - │ ├──── xc_ymodem.c Ymodem传输协议(默认关闭,在xc_shell.h中启动)
. a8 l2 J) b. |" E8 C - │ ├──── xc_iap.c Flash的IAP操作,需要bsp_flash.c驱动支持6 {' ^# Q% C) p" J% i& j) W4 e+ k, P
- │ └──── shell_iap.c shell的用户脚本模板
# b1 K: O" r$ @' D( Z0 ?: Y - │
2 @% l; @: E2 g6 p* c6 @ - ├──┬──SHELL_INC SHELL头文件4 G1 `3 y6 H+ X( C
- │ ├──── bsp_type.h 驱动结构定义
2 w4 U# L( g1 U0 p- p - │ ├──── xc_shell.h SHELL头文件: c7 r: }1 X6 b% \! D0 J$ J
- │ └──── xconfig.h 硬件无关配置文件0 R1 p; o0 v$ B# ]; Z1 l. \
- │6 X( y# Y3 x; k% G, ?7 }, S& K
- ├──┬──STM32F10x_StdPeriph_Lib_V3.5.0 STM32的标准外设库
+ y' t: d. W3 I( M6 x6 _; C - │ └──── ......
4 H( C& C4 o8 `, X - │# p9 _- v" X. R- X
- └──┬──USER 用户文件
D" m# p1 V ?) x - ├─ .....
8 I1 y" o' M; K2 n' D - └──── main.c main文件
复制代码 % V0 R( Z6 [$ |
4.2 工程设置要点1) 设置使用微库: 2)配置包含和路径,注意使用了“--c99”标准,如图 3) 编译工程,无错误警告后烧写程序到开发板运行。 4.3 最终效果按图输入一下指令,SHELL平台会回复相关信息。其中输入“led set 0=1”会将信号1分配到物理LED0上;输入“led set 0=2”会将信号2分配到物理LED0上。这样用户编写程序代码时相当于拥有了超级多的LED信号可用,调试时序非常有用。 5. 添加自己的指令脚本5.1 源代码示例假设我要编写一个自己的指令脚本, 来读取MCU的关键信息,关键字为mcu, 文件命名为shell_mcu.c;当输入“mcu rd 0”时显示MCU的FLASH大小,输入“mcu rd 1”时读取MCU的唯一ID信息。shell_mcu.c源代码: - <i>/*********************************Copyright (c)*********************************
. @7 d+ n8 O4 g# d! ? - ** g7 u: c& \- y
- ** FIVE工作组
: L- \! D5 e* a, X5 o: D7 C - **
) @* g+ R9 \3 G! j6 P; X* j - **---------------------------------File Info------------------------------------5 w2 a+ F2 M/ o0 b
- ** File Name: shell_mcu.c' e) M0 L; s9 M
- ** Last modified Date: 2017/9/17 15:13:57' ]6 g2 Q L/ x4 q5 j$ \" Q" t
- ** Last Version: V1.0
& V# }& o! U: U5 s& A7 J6 i - ** Description: shell测试9 o. P* W1 ]! U" y9 Q) P- |
- **
2 Y c! \" I e4 o& y/ `; f& q; l - **------------------------------------------------------------------------------$ o( U/ Q; I; |) X* Q( h2 j) V
- ** Created By: wanxuncpx
$ H( U' `3 n G& I" Z - ** Created date: 2017/9/17 15:14:08
; H# O. ]" |; F; y% w - ** Version: V1.0
2 i# ^7 q1 R/ T& p. r - ** Descriptions: none
" E8 x8 L0 w) D - **------------------------------------------------------------------------------% R A" m. ~4 N# ^9 T: Z
- ** HW_CMU: STM32F103
1 |8 U/ @) m3 g J& L- @ - ** Libraries: STM32F10x_StdPeriph_Lib_V3.5.0
6 b0 a8 n! ]: v# w: D- B1 p( H - ** version V3.5
/ k7 Z' V. z) m: e0 R) M! o - *******************************************************************************/</i>1 H. g& I% I6 f7 x+ g- e/ C+ p
- $ R0 Z ]/ q3 g; v
- <i>/******************************************************************************
- D6 \! _+ l! D4 N w! n - 更新说明:
% E( K( `1 i: {0 @* _ - ******************************************************************************/</i>) ~" w) U {! J4 ?* d
-
# y* \. D7 Y5 S3 }' h- U5 O9 t. Y! p - <i>/******************************************************************************3 z: ]: x/ X E2 ^
- ********************************* 编 译 控 制 ********************************& K, O% z6 A( x/ o5 E! j$ E
- ******************************************************************************/</i>
: c F9 B1 Q3 H! k/ s- |! h1 p - #define MCU_SHELL //注释掉时屏蔽iap shell功能% D! O& e- b0 w, o7 H3 r
- L; o( j" t8 @8 ?" J' C2 Z
- #include "xc_shell.h" //Shell支持文件,含bool,uint8_t..以及串口数据收发操作
x0 H+ y. e H5 W - <i>/******************************************************************************4 t, p$ h- R- J$ n. p" \' z- z, \
- ********************************* 文件引用部分 ********************************
9 c5 Y" h3 R% N$ U# I - ******************************************************************************/</i>0 c; t6 T+ _6 A
- <i>/*---------------------*
# Z; C4 C4 b$ c Q) T& [) ^& n - * 模块驱动引用
( M! M; L+ s" f! C! S; z - *----------------------*/</i>- H# C: W7 k( _9 |9 f
- <i>//#include "net_w5500.h"</i>( C% L; d7 J3 F: K; _) {# y8 O+ n
-
8 H$ F1 ~, y9 K: b2 | - #ifdef MCU_SHELL+ ^3 u) W) l! [- w9 D1 I
- <i>/******************************************************************************1 ]2 l# z( N+ x8 \* Y7 l; e8 F
- ********************************** Shell实例 **********************************
3 K& P3 K l, ?: D. h w" A9 R" ~) a - ******************************************************************************/</i>/ D$ H5 W4 v. U+ R2 t$ G3 O
- <i>/*---------------------*
; S$ }( J* r! N9 l - * CLI指令服务2 }5 Y$ x0 S3 G& x! j
- *----------------------*/</i>
4 K" k) c- O4 J! g6 _8 L- i - extern bool Shell_MCU_Service(void * pcBuff, uint16_t len );2 |; A: X* v" X$ e' u3 r& V
- 8 p3 e/ g2 F* w* n
- <i>/*---------------------*
: x" {& W1 ~* e" x" x+ i, l - * CLI 结构$ |* L: l b# i& k/ }) U9 n. ?
- *----------------------*/</i>
+ {7 t" u# x8 g7 V# S2 s) j - const Cmd_Typedef_t CLI_McuMsg=
$ C6 K0 S9 P! N" q7 i& r - {
; F1 x5 u. D. A1 g9 n$ m - <i>//识别关键字</i>. k+ p6 b X6 b% P/ o
- "mcu",( a1 Y8 n9 v9 G) z E ~
- 3 J. |* `+ ~+ f) m) B5 P
- <i>//帮助内容</i>+ r6 S9 b& {( c
- "[mcu contorls]\r\n"
! L/ S$ a% U+ S( N - " mcu rd <d>\t\t- Read FLASH information.\r\n"
/ S( h& J5 k: F4 X5 i/ @ - "\r\n",- R, d6 H" @, U/ ?9 I! h
-
0 H% \4 m4 F3 l/ ^ - <i>//处理函数</i>6 s T$ u$ i7 X" F* w6 h+ s. [ n
- &Shell_MCU_Service," z% M; \" t' H0 Y% Q0 J$ Z: o
- - D+ Q9 X2 C" F+ `. }, @
- <i>//附带数据</i>
4 `, x$ x5 {$ \( p( B - 0,
* G$ f) w/ o; a - #ifdef SHELL_USE_YMODEM
9 p- |* ]- M; {3 ~ } - <i>//存储介质</i>* A" |* M4 n- ~8 I8 F$ P# y9 F
- NULL,
( j$ |- A1 x, J6 G! W B6 X - #endif5 Y7 b% K& a3 K T
- };) @3 z* B* w- R2 v3 ]; y6 n
-
; J+ O# x5 { _5 m9 t/ E+ y7 ] - <i>/*---------------------*
. r& P! H' [6 }6 d7 x - * CLI链表节(输出): B2 ]& r5 c4 [2 v6 B' v" q
- *----------------------*/</i>
8 @9 H3 z# O9 \; `3 \ Q0 d) v4 Y - Cmd_List_t McuList = {&CLI_McuMsg ,NULL}; <i>//IAP指令链表</i>3 f+ x& T2 T; F: F$ H7 K) _9 h L
- 6 e3 B7 S. p3 w/ t9 @8 Z
- <i>/******************************************************************************
; h- c6 C) \9 H9 y- b% K$ N - ********************************* 函 数 声 明 *********************************
! H8 O1 Y+ w& L a9 y9 k" \ - ******************************************************************************/</i>
) y( g# C) u# U A, I5 f# N9 c' S$ T - <i>/******************************************************************************
( ~& v4 O/ G: d; c0 \ - / 函数功能:STM32F103控制函数
+ u' K1 _& ]9 _* c/ L! D - / 修改日期:2015/7/14 20:22:02
9 G1 p6 A# d- ?& o& v - / 输入参数:none& g- m" ?, a: J) \1 m) Y4 M
- / 输出参数:none. H8 U' S4 O+ t& I! x8 l
- / 使用说明:需要执行约10s$ v: u% ^! X9 }" U
- ******************************************************************************/</i>( s5 W( |' J! Q6 N3 k
- static bool FLASH_ioctl(uint8_t cmd,void * param)
; j8 t2 k) A# {+ D& O, _& { - {
& q" V0 R. E0 F0 T2 [ E - #define UID_ADDR 0x1FFFF7E0 //闪存容量寄存器,值对应KB单位
6 ]0 \* l) ?5 y! [9 i- ? - #define MAC_ADDR 0x1FFFF7E8 //MCU的唯一ID号,共12个字节0 \- s# c, {/ z L6 t& {) R* F# V
- #define UID_SIZE 2 //UID的字节数, X6 V3 q& |$ l
- #define MAC_SIZE 12 //MAC的字节数5 l: z3 r$ Z8 o! a# \
-
& l: s/ p6 D* J7 @# ^6 ~ - <i>//step1: 检查参数</i>% E$ Z$ _8 \- q& O2 _
- if(!param)return false;
- a5 f. b" v$ W8 d: U, u -
+ e2 g Q. j5 N8 b4 j2 q6 X - <i>//step2: 处理数据</i>
! H- n3 {* p5 S - switch(cmd){
6 @$ J4 G) K( [0 _. Z) k6 _% K% R - case 0 : { <i>//获取FLASH的的UID</i>
1 h- K |$ c0 _ - uint16_t * ptDst = (uint16_t *)((uint32_t)param+1);
1 t; O8 M* A2 t& @! j. U3 @/ S -
8 U G- g) c; t' A8 F) d7 `7 M1 u* H - *ptDst = *(uint16_t *)UID_ADDR;
6 b2 i; ?" z1 \ - *(uint8_t *)param = UID_SIZE;
! q% m, |* O' I' e' G$ P1 c: o - return true;
8 O7 D% B) h8 [! j5 s - }
* q# G, x) j4 h: Z v$ T; \ - case 1 : { <i>//获取芯片的MAC地址</i>
?" n7 M4 ~8 V" `# } - uint32_t * ptDst = (uint32_t *)((uint32_t)param+1);- `- U; j7 Y- e+ E& i$ M: b$ W
- uint32_t * ptSrc = (uint32_t *)MAC_ADDR;
: F- a' f3 `( R4 p6 J- `5 B - % Y! ~7 `2 Q; |4 q' Y' ~2 ~
- *ptDst++ = *ptSrc++;; L+ z6 V4 X* c
- *ptDst++ = *ptSrc++;5 \/ {6 J+ Z- N; n
- *ptDst++ = *ptSrc++;
4 u( E* o+ P/ l5 ~ k/ I - *(uint8_t *)param = MAC_SIZE;
! ^( h, e. Y) ] - return true; S! K B; N0 y7 J, R2 f
- }. _8 q! ]. S+ }6 C `1 i% N. g0 c
- default:return false;
' w6 o1 O( _9 m d - }8 r& r/ |3 ?7 g# q) ?: g7 G
- }$ S) t# I* n; G. _' u5 e/ V- V; { N5 g
- ) C1 N0 x/ J) ]+ V8 C7 w
- <i>/******************************************************************************# i# t* g1 s1 \; R
- / 函数功能:文件系统Shel指令处理" u) V) w, B/ ~% }1 h$ t3 s
- / 修改日期:2013/9/10 19:04:15+ `: ^* E% L- i3 p) x# ^% W3 o
- / 输入参数:输入当前的程序版本
+ P2 Q0 f% L8 d+ j" e - / 输出参数:none# C0 y I2 f1 g* R% ?; M; w3 U0 e+ f: C
- / 使用说明:none
3 t$ F8 u1 p- h1 g - ******************************************************************************/</i>
6 k( Y# w( o% B2 L0 n5 K - bool Shell_MCU_Service(void * pcBuff, uint16_t len )
6 l$ l3 y( z6 {1 j - {( a. j0 Y8 [8 I6 x
- uint8_t *ptRxd; <i>//用于接收指令处理</i>
! w K: m# d( W' B( c+ M - int i;! |0 l& _9 g0 m( H
- uint16_t retval;
; u; a5 _( f8 K& \9 Y% R* r( ] - uint8_t buff[32];- A" Z9 E/ t+ A# d
-
. U7 ]3 O9 u% g9 C8 w" @ - <i>//处理指令</i>8 F4 s9 X2 R. \
- <i>//--------------------------------------------------------------------------</i>0 }" D, f3 p& F$ X3 e7 C
- ptRxd = (uint8_t *)pcBuff;- M, ^: u1 O' z
- ' B3 ~0 p& v. H' g- o+ L, ~2 z
- if(StrComp(ptRxd,"rd ")) <i>//读取FLASH信息</i>+ @' G) X2 E3 p3 O9 j
- {7 V7 z& m2 R- Q' I
- int wval;
$ S6 E) [# i6 L" \- T -
: O8 r" p0 T$ k7 y+ f7 g - if(1 != sscanf((void *)ptRxd,"%*s%d",&wval) )return false;
$ z8 t" Y+ G' f$ t - if( wval>2 )return false;
6 Q( D. p1 r0 I, f3 r' l2 j- T - if(0==wval) {
% H0 f4 Q. a6 k! g; y - FLASH_ioctl(0,buff);
, K/ v% A" d+ @7 ], K - retval = *(uint16_t *)(buff+1) ;! `& v; w" x6 b
- printf("->Flash:\t%dKB\r\n",retval);
1 S$ I' H) ]3 o1 q- u' Z3 O - return true;
4 C8 M9 T( F# i a- ]" r2 o5 ? - }- ^% M* l( T5 w8 V8 W0 W
- else if(1==wval) {& S" H/ e1 i" ~: {1 D/ p
- FLASH_ioctl(1,buff);8 ~8 y, t$ C* U. y$ i4 A
- printf("->MAC:\t ");: `6 W; Z* @/ v( n7 u
- for(i=0; i<buff[0]-1; i++){printf("%02X-",buff[i+1]);}
6 _/ v8 y' J7 Y - printf("%02X\r\n",buff[i+1]);
3 M6 o; H3 i5 S3 `- A [: E - return true;
- y) n7 Y; K/ | - }
( t5 U! U. Q9 j' E: N5 ] - else return false;
$ b9 n( ^; T) k% K# L) _: d - }. o6 |- p9 ^; R, n# R1 z
- else if(StrComp(ptRxd,"help\r\n")) <i>//指令帮助</i>6 y1 d) z5 q- B, h/ h7 t) l1 `" `& k6 s/ ^
- {/ Z7 V/ R2 ~2 t
- shell_SendStr((void *)CLI_McuMsg.pcHelpStr);
" C. h' k4 g" E7 L - return true;, R" ]6 Z% I3 U: K, S4 C3 h7 M
- }
7 x9 u5 U, B8 B' v1 h - else return false;
2 Z* u; c$ j6 Y7 x: L' v0 @ - }
1 s/ @) l2 U. Y& K) ^+ ?, k - ( H9 u7 ?% u5 g5 B% `" C
- <i>/******************************************************************************
) T7 T; f+ n! Y4 A+ x$ @# D% r0 ^; R% m - *********************************** END ************************************1 A, H! B) o& F
- ******************************************************************************/</i>
0 W9 Y) d7 \# D( X/ m. H" c' _# s/ E - #endif
复制代码 8 V) P" m. p6 n; r1 Z, v+ K
5.2 实现步骤1) 将该文件添加到工程下。 2) 在main.c中用extern 引用McuList,源代码为: - <i>/*---------------------*
1 N n. b1 Z' @ d - * Shell指令链表5 G$ D/ h/ Q9 a( E( L
- *----------------------*/</i>
; k# y8 q z% F4 }' W. |* m5 F' F - extern Cmd_List_t McuList;
复制代码
4 X; I( |& W3 K" A5 K1 b" C3)在main.c初始化时添加: - <i>//----------------------------------------------------------</i>+ r1 g# \5 o; p0 U4 M" c9 K
- <i>//step1: shell初始化</i>
5 z% N' f* _, Y3 ]. D) | - shell_Init(115200,ledx_cfg); <i>//初始化shell接口</i>
6 ]/ I8 m' p" T+ Z8 Q - CLI_AddCmd(&McuList); <i>//添加模块指令到链表</i>
复制代码 j# u: v1 H1 v, a8 `
4)编译工程文件。 5)下载到开发板运行即可在终端下看到新支持的CLI指令:
! |% i, V: }6 k3 Z& F+ n
+ d3 H+ h" r- b/ L3 Q6 x# C# H+ d( A( ?: \
|