|
1. 前言 玩过Linux的朋友, 是不是对Linux无所不能的串口Shell命令控制台羡慕不已, 要是自己做的STM32F系列低档次的MCU也有这种控制交互能力, 会给调试/维护和配置省下多少麻烦事呀, 比如启动/关闭调试或自检模式, 打印调试信息, 配置系统参数, 传输文件等等, 也有相当多的朋友凭借自己出色的编程能力可以实现这些功能, 这里提出我的这个解决方案, 以作交流. 本平台(xc_shell)具备以下性能特点: 大量主要代码, 和具体硬件无关, 移植性强,代码文件少. 只有在处理用户的输入命令时, 才占用CPU资源, 且代码可裁剪到1KB SRAM和4KB Flash; 用户可以非常灵活的添加按模板编写的命令脚本文件, 自定义扩张能力强. 支持操作系统和非操作系统两种场景应用. 支持Ymodem文件传输协议 支持将Flash的扇区开辟为参数区, 可实现本地/远程升级。 实用Led灯信号管理, 可将65535虚拟信号灯选择输出到1个实体LED灯上, 调试时序和状态非常有用 拥有基础的LED管理, 调试模式设置, 命令帮助指令, 复位指令等基础功能
6 _0 q3 Q' ]9 I: ]* ~! _1 j
7 } B6 y( d8 {% p+ q5 M* |) i7 L+ l) f
功能越多设计会越复杂, 为了解释清楚代码, 先向大家解释一下以上功能的基础实现原理, 并提供一个最小的的源码工程。 # }" ^9 ^( j. {
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>/*---------------------*
5 E- v* u7 T; s: K& J! l - * 指正函数定义
! b0 I/ J, t2 V9 Y - *----------------------*/</i>2 h) C* O( _& F! \
- typedef void (*pvFunDummy)(void);1 d; C' v- v* m( t D) _+ m
- 7 V8 N$ ^5 P$ S- j+ p8 C+ W2 {5 R. [
- <i>//输入整行,输出逻辑</i>2 F$ L! l, ^+ h o# W5 i
- typedef void (*pvFunVoid) (void);
B' o2 Y2 w; L6 }0 M6 W - typedef void (*pvFunBool) (bool bVal);! O ^, P+ m0 h
- typedef void (*pvFunChar) (uint8_t cVal);
# n" d" F& U# P/ V0 j( ^/ N- y - typedef void (*pvFunShort)(uint16_t sVal);& v- ]' Z4 ]" H& ~0 W5 F; ?; ?
- typedef void (*pvFunWord) (uint32_t wVal);
5 E+ j6 H0 [# ~# v -
$ `3 l: m. f. O) P. L" V - <i>//输入整行,输出逻辑</i>
8 R" U5 K2 o, W# {* S6 L) \) ]# ?2 F - typedef bool (*pbFunVoid) (void);
+ L" ?8 k: e( n f# [& B& C - typedef bool (*pbFunBool) (bool bVal);. r- w, ^4 f8 o
- typedef bool (*pbFunChar) (uint8_t cVal);- `8 Z K, `$ \
- typedef bool (*pbFunShort)(uint16_t sVal);
) K, i$ Q2 N; o q3 a, P2 Z - typedef bool (*pbFunWord) (uint32_t wVal);7 ?2 B6 {% `, ?8 v# x$ K
- ; |; P9 K% u0 M1 J& Z3 y& G
- <i>//输入整形指针,输出逻辑</i>4 o2 K4 W7 Y) [5 R# }7 N. ]
- typedef bool (*pbFun_pVoid) (void * pVoid);. y9 N4 S! v) } r$ a
- typedef bool (*pbFun_pChar) (uint8_t * pStr);* x; _7 _+ ?7 o* q; L( p( l
- typedef bool (*pbFun_pShort)(uint16_t * pShor);/ Y, X5 h6 [/ q0 T
- typedef bool (*pbFun_pWord) (uint32_t * pWord);
; [1 S; [. A/ l$ F, r& `) h1 t - $ z2 C! T# O( x7 I2 N
- <i>//输入数据帧,输出逻辑</i># Q% T* P- [' W5 I* u
- typedef bool (*pbFun_Buffx)(void * pcBuff, uint16_t len );
; i2 l7 K) m( b2 c - typedef bool (*pbFun_Bytex)(uint8_t * pcByte, uint16_t len );, [8 R' ]4 N& Q% `
- <i>/*---------------------* 6 j3 F V) C9 |
- * TTYx 句柄结构' l% U- R( i4 [& E; M6 |4 G( Q, f
- *----------------------*/</i>
x7 u; ^/ F6 y9 ^ - typedef struct TTYx_HANDLE_STRUCT 5 G2 h+ U/ v: k6 k7 { X% F5 Q" I; _: F4 t
- {
% ?- ^+ M6 A/ \) q, s$ K5 H - const char * const name; <i>//驱动器名</i>
$ l% }) `6 D+ X) ]! L6 L - const uint16_t rxSize; <i>//接收大小</i>+ i- N: {$ N6 _: K% F' S. I* I
- const uint16_t txSize; <i>//发送大小</i>
& \& ]9 b# Y) v! @: v4 T+ J -
: t6 @! a2 D/ @+ |) r2 F5 \ - <i>//------------------------------------------------------</i>( C& O( R, o% R6 t1 N. @
- <i>//step1: 用户可用API</i>
$ o4 T6 `) h. h, l! ]3 ]* P - const pvFunWord init; <i>//初始化.</i>7 P/ b v0 \% H
- const pbFun_Bytex api_TxdFrame; <i>//发送数据帧. (发送帧)</i>% h. H# J" J- N4 X7 C9 {, d
- const pbFunChar api_TxdByte; <i>//发送数据字节</i>2 q( r1 x7 o5 p7 y! U1 M6 d' T
-
# m1 ~, ^$ |* V; C. F! U - <i>//------------------------------------------------------</i> x/ R2 G: x. s# f% k- f0 U
- <i>//step2: 注入回调函数</i>
2 b, W4 `4 f; k1 u - pbFun_Bytex inj_RcvFrame; <i>//(ISR)接收数据帧. (接收帧)</i>
4 _. J/ ?2 I! x - pvFunDummy inj_TxdReady; <i>//(ISR)发送完毕回调</i>
& g# K9 e, }/ _! L& H -
! r; t }9 }& H: f+ K - <i>//------------------------------------------------------</i>/ c+ g5 l- m; ]
- <i>//step3: 接收回调函数</i>
7 j1 ]5 G2 O+ ^4 O$ K - struct TTYx_HANDLE_STRUCT * pvNext; <i>//连接到下一个指令 </i>
! m# i6 z) g/ n7 A) b% v7 Q# I' w - }TTYx_HANDLE;
复制代码 可注入的命令脚本(CLI)实现
+ n+ u# w& M. w2 I, ?! w' v, b$ @- 命令CLI也是一个结构体对象:6 h+ J+ O4 Z% P, w
. I7 I3 ]. h% N% k1 F# M
. e' T8 Y s, y0 a7 `
) d) K8 W: V# A" b- <i>/*---------------------* / K' |1 J5 B7 q6 a& V$ F
- * CLI指令
7 Z( X [: ^: K1 J - *----------------------*/</i>
8 Z. w6 b+ g* \; p2 v1 Z) d - typedef struct
$ N4 y4 G2 M1 i3 P; m; h4 ] - {9 |: q# a0 J' |: R
- const char * const pcCmdStr; <i>//指令字符串(只能为小写字母)</i>& B; }: f' N$ @; k& C& X0 W
- const char * const pcHelpStr; <i>//指令描述,必须以:"\r\n结束". 比如:"help: Returns a list\r\n".</i>5 \6 ?- y1 q+ f" L- q& I7 p: I; |
- const pFunHook pxCmdHook; <i>//指向回调函数的指针,处理成功返回真否者返回0;</i>
. d& Y7 B4 u5 j: g5 L - uint8_t ucExpParam; <i>//指令期望的参数个数</i>/ h$ D7 D; v5 v% K# e5 V4 |/ D7 r( |
- const MEDIA_HANDLE *phStorage; <i>//指向存储介质,没有的话填充NULL </i>* I; A) ?$ f& Q' s7 V
- }Cmd_Typedef_t;
复制代码 0 i# `' b0 L8 r# @' i* q
各位朋友可能会使用到非常多的自定义CLI命令, 格式诸如这个网卡的命令: - const Cmd_Typedef_t CLI_WizMsg=
4 Z! p) u8 a/ _0 t - {7 V- K& O/ g. J! k- t( J
- <i>//识别关键字</i>
0 l, z }# P+ }& I. m - .pcCmdStr = "wiz",( C- D" ~4 _, z- l! M, H, B7 M
- <i>//帮助内容</i>& G9 x. G( A- t& x! s: v: y4 X/ X
- .pcHelpStr =! x$ Q' G% ~7 ]* H) h
- "[WIZ contorls]\r\n"+ A8 H7 \$ O: ^
- " wiz help\r\n"+ n. b: r" V0 T
- " wiz rd info\r\n"
( X$ [+ A* v s- _% g( |' ]* ]$ h" U - " wiz reset\r\n"
/ D$ n7 ?; i( e) x0 a, W - " wiz wr ip <D0>.<D1>.<D2>.<D3>\r\n"
* u& i# o. _- S1 b7 T; M$ G - " wiz wr mask <D0>.<D1>.<D2>.<D3>\r\n"* `2 z* `8 ~( `; F
- " wiz wr way <D0>.<D1>.<D2>.<D3>\r\n"
0 J) z V" s& v: S, N, c - " wiz wr mac <H0>-<H1>-<H2>-<H3>-<H4>-<H5>\r\n"
5 P6 l; J9 f, s. y* z& s. G3 U- j - " wiz wr port <udp> <bak> <vol> <pic>\r\n"* z2 f4 E$ j( ?+ z' v6 Y; Y
- " wiz wr sip <D0>.<D1>.<D2>.<D3> <port>\r\n"
6 {6 P; z h% f: A+ F. ~' R - " wiz wr cip <D0>.<D1>.<D2>.<D3> <port>\r\n"
! }+ b+ T& s8 @; I - " wiz load default\r\n" N% ?& M$ m: [. p' J
- "[WIZ Test mode]\r\n"
1 q9 [7 ?9 Y' K/ c9 s- Z - " wiz loop open\r\n"
- `* R {/ _/ B. w1 O - " wiz loop close\r\n"
3 p4 M1 D7 l6 F: {) Z4 c - "\r\n",
, w1 L# r3 ^9 @ - % W: S' `& X* h
- <i>//处理函数</i>
, t$ i1 l0 K! P4 t - .pxCmdHook = &Shell_WIZ_Service, <i>//见实体函数</i>' e" J0 A+ E. U. w! m. q
-
+ G% E6 [9 c4 ~. f* Z - <i>//附带数据</i>6 F: v) M; Z/ |( [
- .ucExpParam = 0,
' n% e& ^1 M; L7 X -
* o5 {8 a! i* ]" w - #ifdef SHELL_USE_YMODEM
8 t1 s7 @2 ?( v( ]% I - <i>//存储介质</i>0 W2 F6 |$ O6 Y6 p/ b& q: @
- .phStorage = NULL,' i& P: g2 }( \ N# w
- #endif+ B1 R& i/ S- U w7 f& I6 P
- }; i& S& T: I! d: u# S. y( i
- <i>/*---------------------*
8 t6 N, W4 X: l: S" W - * CLI 链表节2 Z, ?6 H* }: c: X' S9 E2 h+ K
- *----------------------*/</i>
6 r, C, F9 u; d* Q% o: ~+ [ - Cmd_List_t WizList = { &CLI_WizMsg, NULL,}; <i>//Shell指令的头</i>
复制代码 0 C, _7 m+ z& H+ ^
如配置IP地址输入“wiz wr ip 192.168.1.250\r\n”则可以了 3. 环境准备
) w" y' ~3 f/ i( g; N8 A" h0 A3.1 硬件开发环境- STM32F103系列开发板一块, 带USART1接口。
- USB转串口线一根。
3 [. t3 R. R+ Z/ C9 ^/ r
; a! E. O- v0 `; }" F' Y# r& c" d, } 3.2 软件开发环境- MDK4.72或以上
- SecureCRT串口超级终端. t: u9 N; s, t* I1 j5 v
* ?: T9 [$ h. @; m
3.3 软件配置在xc_shell使用“/r/n”作为命令的结束符, 而SecureCRT按下Enter不是输入“/r/n”故而需要按下图设置:此外在《终端》/仿真/高级中选取【本地回显】 4. 代码介绍
! A- C3 \. t5 I- t; ?& X) B% g7 o4.1 目录结构□ XC_SHELL! U+ Z! k2 S( M$ T
- ├──┬── BSP_LIB BSP库,硬件相关驱动代买
l, }; C7 l3 } - │ ├──── bsp_ledx.c 基础LED驱动 : u0 S* Y2 B1 w
- │ └──── bsp_tty0.c 调试串口驱动* S8 f) v0 F2 o1 v9 E( G6 S
- │ e. Z4 M. @0 P9 u8 U1 L
- ├──┬──MDK-ARM 工程文件
0 c, e7 ^9 R" C' Q( S2 p- f" t - │ └──── Project.uvproj% _; M& G( w1 ` x- C$ X: o& @
- │8 n8 K) y0 ?( m' J0 y6 Y% b! p" @
- ├──┬──SHELL_CFG SHELL配置头文件 f& o! I! w. W6 [1 {
- │ └──── user_eval.h
. s/ T1 o9 `1 _3 `/ W- v9 h; o' l - │( Q4 i& u. h4 E" l* z
- ├──┬──SHELL_CORE SHELL内核文件
0 ]$ b% P6 l$ ^. I4 q- R) H8 {- F - │ ├──── xc_shell.c SHELL内核文件
3 u. Y% A4 v1 c& S% _( o) | - │ ├──── xc_ymodem.c Ymodem传输协议(默认关闭,在xc_shell.h中启动)
* T6 T7 `4 x1 w0 T - │ ├──── xc_iap.c Flash的IAP操作,需要bsp_flash.c驱动支持9 h( z2 f' P8 ~
- │ └──── shell_iap.c shell的用户脚本模板" w9 Z2 h' A7 d8 {
- │
M: ^7 ?2 u) U% ~# q) g - ├──┬──SHELL_INC SHELL头文件
* u* e) y9 U% z( n$ I - │ ├──── bsp_type.h 驱动结构定义
7 c( x+ n' {& @" W - │ ├──── xc_shell.h SHELL头文件8 i2 Y; C2 @; x' ]$ e
- │ └──── xconfig.h 硬件无关配置文件
! R6 g" O/ f& y6 Y# C - │9 r9 ^2 P+ t/ G9 A% m0 d0 k
- ├──┬──STM32F10x_StdPeriph_Lib_V3.5.0 STM32的标准外设库
( u$ Y$ ~8 s7 y9 r6 Q6 _: _ - │ └──── ......
) @* E4 k; t' I4 T; {6 R) L - │/ _* r' S" I" ~7 D. n, R C& M
- └──┬──USER 用户文件
9 w4 {: e/ Q3 a: z - ├─ ..... , d8 L" J5 R# s+ R- P7 ]5 E, u* M
- └──── main.c main文件
复制代码
" F0 e9 S5 @6 O3 k/ N3 A: C4.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)*********************************1 {- b+ A9 P5 ^3 \( }! X
- ** ' P7 n3 s; ?7 X) G7 j$ [( U1 |
- ** FIVE工作组
0 g$ p8 ]& i k- Q - **2 E4 n% _ N; f3 Y2 G
- **---------------------------------File Info------------------------------------
: N3 R. t- N( z - ** File Name: shell_mcu.c4 X; I; r4 {. h; g7 [1 q
- ** Last modified Date: 2017/9/17 15:13:575 Z6 f, {7 ^1 u1 A1 B( v
- ** Last Version: V1.04 F) G$ L2 J9 F. E* g( @
- ** Description: shell测试# u8 N) c1 G2 g
- **
( g+ e& S( b( F - **------------------------------------------------------------------------------
* g4 R* F |7 C8 q7 k: C - ** Created By: wanxuncpx
$ h9 D4 I; A7 n3 q4 B - ** Created date: 2017/9/17 15:14:081 F. @6 g* U9 U4 c2 V& q+ d3 L' ]
- ** Version: V1.0
7 v! d6 ?. l* R4 b& @9 K - ** Descriptions: none
4 z+ O# u+ y5 N6 G) f7 `. b - **------------------------------------------------------------------------------
9 I; C" l1 H. A - ** HW_CMU: STM32F103
8 t3 @1 F% H, U4 I1 I - ** Libraries: STM32F10x_StdPeriph_Lib_V3.5.0% @6 L4 e# ]' A9 p
- ** version V3.55 ?0 z) Q/ i6 N( ^$ Q Z. o
- *******************************************************************************/</i>: Z8 Z! j f/ c) [" h
-
+ m) E) O+ \0 o) g+ r! ~( g% | - <i>/******************************************************************************
0 B% I7 t0 e; a - 更新说明:: E7 _9 ?8 V! Q, B* m
- ******************************************************************************/</i>8 r, L# [- y( m6 Z+ u- ^
-
; J3 c6 b! Z$ J! z. Q - <i>/******************************************************************************0 ?! d5 U: t# b t+ n
- ********************************* 编 译 控 制 ********************************
& ]5 i' Q- W R. p. W* w2 i" P - ******************************************************************************/</i>
- M7 I1 K5 ]4 j7 Y% J+ ]# X( F - #define MCU_SHELL //注释掉时屏蔽iap shell功能
" a1 u E8 _% R$ _5 R7 C& t0 a -
- Q6 l8 a8 D# ~ - #include "xc_shell.h" //Shell支持文件,含bool,uint8_t..以及串口数据收发操作
h9 s1 S4 C; @+ E9 @6 b - <i>/******************************************************************************' u7 k6 m- M+ U' H" q
- ********************************* 文件引用部分 ********************************
$ @. H! E7 r& t3 X: k9 d - ******************************************************************************/</i> D2 G* h6 q/ ~& f- V5 U% b& O
- <i>/*---------------------* % D7 L1 H: L" ?$ g0 O4 K
- * 模块驱动引用; Y( h5 v9 ]( q# l! K) r; f
- *----------------------*/</i>
* s! b/ b# h8 ?3 R { - <i>//#include "net_w5500.h"</i>
) v: K# ]8 h* v w - , q) e `! I0 E4 @1 t
- #ifdef MCU_SHELL h7 e% l1 {! n3 x7 x5 ]
- <i>/******************************************************************************" M3 f6 O1 E& a" |- s9 v
- ********************************** Shell实例 **********************************: {0 M4 \! `" o2 {
- ******************************************************************************/</i> U5 O5 J! A8 F. w
- <i>/*---------------------*
& o" S# q- E2 [: q/ l - * CLI指令服务5 D# M0 s/ r i# P% p9 I9 K
- *----------------------*/</i>5 c. j& Q0 m" v; e
- extern bool Shell_MCU_Service(void * pcBuff, uint16_t len );
# b; x+ i- r$ i -
& v4 ?2 R) Y# t- B* Y - <i>/*---------------------* & V. ]# z* u! v, W% z& R
- * CLI 结构" f+ i$ b; s) x/ l% T4 K
- *----------------------*/</i>
- F3 @' g# n+ @ - const Cmd_Typedef_t CLI_McuMsg=
; B7 h! J" L# Y/ ? J& `& u3 }/ M - {. T: J. @- d, v
- <i>//识别关键字</i>
6 n1 S, [' W) ^) R$ ]$ G! x - "mcu",
6 _. b: o3 Y( r, v. {& O! p0 C - 0 i" n: J! R8 C/ {) K- h2 u) A
- <i>//帮助内容</i>
' S1 }7 f4 r! P' a - "[mcu contorls]\r\n", T1 [* _2 `$ P4 n
- " mcu rd <d>\t\t- Read FLASH information.\r\n"
! L5 Z* V0 ]6 \ - "\r\n",: o! D: T& F- r6 {# Q" f" u
- / j6 O8 C+ ~# X8 w- E( x _
- <i>//处理函数</i>
4 f4 `6 ?9 C6 ~- @! O - &Shell_MCU_Service,/ h7 L4 ]7 ?' l$ T" z( p+ Y
-
5 I% T% V; E1 X7 o5 F - <i>//附带数据</i>( o9 D8 S: W; r' {0 X- V1 X$ w
- 0," H6 b" E/ I) X4 H5 t
- #ifdef SHELL_USE_YMODEM 0 v4 }$ W- }& ~2 d/ U2 c* Y+ O
- <i>//存储介质</i>9 K- [1 n$ N/ Q; a
- NULL,
% Q9 w! A4 ]% x1 J# g - #endif
0 z8 {. r) |# i" T" K: j - };
" ]3 q1 e% j* l3 A# G J -
0 J, H; w/ I1 f7 o: {7 g9 o - <i>/*---------------------*
0 l) O# L: e" K$ b$ c - * CLI链表节(输出)- `' x4 i4 \, {* F. c
- *----------------------*/</i>, ~9 R: G5 ^9 o
- Cmd_List_t McuList = {&CLI_McuMsg ,NULL}; <i>//IAP指令链表</i>( ^' m1 Q# J" Z s, U1 \
- # q- o3 `5 [3 \7 D1 c; Q$ `
- <i>/******************************************************************************4 M" d6 b/ l5 a3 y" Q% ~, k
- ********************************* 函 数 声 明 *********************************
8 v7 e$ A( a0 P: }; W5 H - ******************************************************************************/</i>; X0 K, P9 M4 }1 c9 P
- <i>/******************************************************************************
- R7 P; U- _8 }+ z. E/ ^9 Z% o, ] - / 函数功能:STM32F103控制函数
& n- Q9 Y4 ^% @0 o- o7 T - / 修改日期:2015/7/14 20:22:02
9 v* v- t! a8 X1 T+ c: K q - / 输入参数:none2 w. R8 j9 v& w8 n6 u! D# m
- / 输出参数:none8 N! V4 w5 T! q- N4 \3 I( `3 t
- / 使用说明:需要执行约10s
; R c% _2 c% y2 p - ******************************************************************************/</i>5 ^4 v5 V+ l) V" Q/ _
- static bool FLASH_ioctl(uint8_t cmd,void * param)0 o7 W. f' M' X: o
- {0 r, W1 I$ H( l9 `6 y
- #define UID_ADDR 0x1FFFF7E0 //闪存容量寄存器,值对应KB单位' T' d' ^. c( ~/ Y/ \: \
- #define MAC_ADDR 0x1FFFF7E8 //MCU的唯一ID号,共12个字节
5 ^% M) f6 M4 a" m$ o) m0 y) i7 V0 P - #define UID_SIZE 2 //UID的字节数8 }( |2 E8 s0 ?4 T
- #define MAC_SIZE 12 //MAC的字节数$ g+ `* i, e' V% q0 C
-
9 ^& s) P0 e4 J& Q - <i>//step1: 检查参数</i>
& c& H; p' E, C; X! L! d - if(!param)return false;
4 ^7 v' x. p1 S. {4 e; N7 J; C -
* s5 _& p y1 k( f- m' ` B5 a/ E; x3 M - <i>//step2: 处理数据</i>
A- n2 R5 L4 [ - switch(cmd){
9 v- |+ _% X1 {; N - case 0 : { <i>//获取FLASH的的UID</i>
0 J- w" o K) e: I - uint16_t * ptDst = (uint16_t *)((uint32_t)param+1);, u4 n ^! p O2 {
- : q$ t8 D3 U0 n$ n( ^- ~) ~7 {2 t! i7 Y
- *ptDst = *(uint16_t *)UID_ADDR;9 }* q5 o" u |( O- i
- *(uint8_t *)param = UID_SIZE;. W- T& ]$ A- | B: M+ ~0 g' V
- return true;( D. {8 q* C# w; V- s6 Z" B% @; S
- }! @7 X# ]9 k& K
- case 1 : { <i>//获取芯片的MAC地址</i>
4 A7 f# {, U" M - uint32_t * ptDst = (uint32_t *)((uint32_t)param+1);7 U( E) h; Z+ o
- uint32_t * ptSrc = (uint32_t *)MAC_ADDR;
& y3 w; A; G, B( T8 x0 ] -
5 U- S/ ~. f3 r7 Y# E5 }, | - *ptDst++ = *ptSrc++;' P: `/ J2 c% C9 r
- *ptDst++ = *ptSrc++;! A1 c) g8 J9 F/ a& X
- *ptDst++ = *ptSrc++;. L- E7 I$ T V$ m( y
- *(uint8_t *)param = MAC_SIZE;, L5 Z. O, G% {
- return true;' u1 Z5 g4 W% J# E" o! n- [7 M
- }
0 h% z6 J( n6 s' p - default:return false;
+ H$ g# k! j; C0 x - }, o2 A% T7 d. O; q3 O! o' F! ^
- }
* m8 Y ^; s3 J -
9 b5 X1 Y! ?) |7 S' t# S) A - <i>/******************************************************************************
+ U8 e1 y& Y# | - / 函数功能:文件系统Shel指令处理 _, l9 V# ]$ C; T6 E6 w9 x7 R2 c
- / 修改日期:2013/9/10 19:04:15
1 ?2 K$ F& y9 } - / 输入参数:输入当前的程序版本
9 g& l7 V/ R; N! |( X - / 输出参数:none
$ _8 |( N) z2 h3 e8 ] - / 使用说明:none
: ^( m7 v: y( p! |% ^" f2 F - ******************************************************************************/</i>6 ?' z5 D* O/ N, @) X- M
- bool Shell_MCU_Service(void * pcBuff, uint16_t len )
4 j1 }3 E5 |" X - {
6 ^8 |" M( B7 z1 _/ h4 u1 p - uint8_t *ptRxd; <i>//用于接收指令处理</i>
) {& B- n$ I2 g& [4 w - int i;
2 d% J: U9 G% z4 a# i b7 M2 s - uint16_t retval;) \1 U q+ S: Z4 I( |- Z4 M+ a
- uint8_t buff[32];' y1 i" z- S, f' ?! u- @* m
-
1 M. p4 f; j( p( {: Z" x - <i>//处理指令</i>2 P5 y4 D7 U* _" C
- <i>//--------------------------------------------------------------------------</i>/ K' m/ F6 r# }: A
- ptRxd = (uint8_t *)pcBuff;
3 [/ f0 K$ L2 t! M* I* K - 3 Q/ h' @% Y8 ~, t6 Y- D
- if(StrComp(ptRxd,"rd ")) <i>//读取FLASH信息</i>
+ n* \8 d! E! X3 r5 H7 ? ^3 | - {
; ~2 A, C, h2 I9 M - int wval;: y' D, U9 L/ f
- 7 ^4 e# r: A1 I& b, ]2 V
- if(1 != sscanf((void *)ptRxd,"%*s%d",&wval) )return false;
7 e ~; X2 z e% U' g( c - if( wval>2 )return false;
; N0 H) u6 ^, v! k - if(0==wval) {: ~* @) {1 h) p4 q) ?
- FLASH_ioctl(0,buff);8 }% i8 ]+ j8 T1 a9 d' D
- retval = *(uint16_t *)(buff+1) ;
1 b8 S- E" a* z. n6 x - printf("->Flash:\t%dKB\r\n",retval);
4 k+ g2 W7 ~+ G0 A: x3 d - return true;+ v' G4 @7 A! r! `/ k
- }: Q( |4 y6 S, h* \0 M* d6 q, I0 \
- else if(1==wval) {/ G& ]* C2 @" t; S% e% r$ o8 t
- FLASH_ioctl(1,buff);
/ K1 v) C. m: Z& j2 G# s5 d' Y - printf("->MAC:\t ");
e; n. f$ J6 L7 E; x: y - for(i=0; i<buff[0]-1; i++){printf("%02X-",buff[i+1]);}2 C5 x$ [# H j1 G4 s& _0 M/ ]
- printf("%02X\r\n",buff[i+1]);
6 n+ v) Y$ C1 f* M) B% K! ^ - return true;
# ?5 P( c6 S( }+ V+ G' r# U, X - }: H; k2 X+ y: f' m6 j6 B, E
- else return false;
7 I/ j h; y# T0 C+ `8 t9 H - }
; [: h$ j/ i; S" W - else if(StrComp(ptRxd,"help\r\n")) <i>//指令帮助</i>' m; N" u! V/ `$ E& c
- {" T @1 [4 Q+ f
- shell_SendStr((void *)CLI_McuMsg.pcHelpStr);
% e& h1 S) P; h6 n; i: j2 W - return true;' h6 M$ M, {) u, L+ a) P
- }0 [$ y }8 A5 |, w1 [8 k+ O; K
- else return false;' g0 w# ?$ o1 H' w
- }4 I- M/ b- a! R; {/ i
- - x, B1 |' Z; M# W* r# R/ K
- <i>/******************************************************************************: y0 R" i4 u/ J" A6 l
- *********************************** END ************************************
1 F( r. | p7 ?1 k - ******************************************************************************/</i>
. N) S% S4 q1 x& y3 K - #endif
复制代码 ! I2 m5 s" k" V8 v, F& ~
5.2 实现步骤1) 将该文件添加到工程下。 2) 在main.c中用extern 引用McuList,源代码为: - <i>/*---------------------* ' J) q# w- ^- i3 L2 u
- * Shell指令链表
4 [' q, `2 E9 \" x1 Z& y - *----------------------*/</i>
/ Q" R: K/ n/ A# k7 C3 v+ ]! A/ m1 v - extern Cmd_List_t McuList;
复制代码 6 {! Y3 _$ B" m1 C2 T! O
3)在main.c初始化时添加: - <i>//----------------------------------------------------------</i>- L- w1 L5 ^; Z- f/ a
- <i>//step1: shell初始化</i>3 u0 T; u# r, ]( h) r! l& N* c
- shell_Init(115200,ledx_cfg); <i>//初始化shell接口</i>
0 ~1 G% Q* F8 x( k1 i - CLI_AddCmd(&McuList); <i>//添加模块指令到链表</i>
复制代码
" ^9 }0 _3 W. ~0 y# _# L( X4)编译工程文件。 5)下载到开发板运行即可在终端下看到新支持的CLI指令: ) b1 f+ f& B0 a( n4 r3 O+ \
7 B* a1 l1 r" p) r* O( y. Z+ F/ L5 K% P
|