Usamrt流程
头文件内容解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| void usmart_init(u8 sysclk); u8 usmart_cmd_rec(u8 *str); void usmart_exe(void); void usmart_scan(void); u32 read_addr(u32 addr); void write_addr(u32 addr, u32 val); u32 usmart_get_runtime(void); void usmart_reset_runtime(void);
struct _m_usmart_nametab { void *func; const u8 *name; };
struct _m_usmart_dev { struct _m_usmart_nametab *funs;
void (*init)(u8); u8 (*cmd_rec)(u8 *str); void (*exe)(void); void (*scan)(void); u8 fnum; u8 pnum; u8 id; u8 sptype; u16 parmtype; u8 plentbl[MAX_PARM]; u8 parm[PARM_LEN]; u8 runtimeflag; u32 runtime; };
|
- usmart_str.h—-usmart字符串的相关操作
1 2 3 4 5 6 7 8
| u8 usmart_get_parmpos(u8 num); u8 usmart_strcmp(u8 *str1, u8 *str2); u32 usmart_pow(u8 m, u8 n); u8 usmart_str2num(u8 *str, u32 *res); u8 usmart_get_cmdname(u8 *str, u8 *cmdname, u8 *nlen, u8 maxlen); u8 usmart_get_fname(u8 *str, u8 *fname, u8 *pnum, u8 *rval); u8 usmart_get_aparm(u8 *str, u8 *fparm, u8 *ptype); u8 usmart_get_fparam(u8 *str, u8 *parn);
|
u8 usmart_get_fname
pcnt & 0x7f 应该表示第几个参数
strtemp每次循环指向一个字符
首先判断接收到的字符串前五个字符是不是void, 设置rval, 是不是需要返回值
注意! 接收完前五个字符, 记得加’\0’ 字符串结束标记, 否则usmart_strcmp无法比较
下一个while判断当前字符是不是’*’或者’(‘ , 判断逻辑是, 没有碰到空格或者 * 就继续循环, 同时res也就是offset加1
根据offset直接跳到函数名开始的地方
继续判断, 逻辑是 fover表示碰到的括号, 左括号加一, 右括号减一, 如果fover是0说明没有接收完, 因为至少有一个左括号或有右括号
判断是不是’,’ 是,temp加一(temp表示参数个数)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
u8 usmart_get_fname(u8 *str, u8 *fname, u8 *pnum, u8 *rval) { u8 res; u8 fover = 0; u8 *strtemp; u8 offset = 0; u8 parmnum = 0; u8 temp = 1; u8 fpname[6]; u8 fplcnt = 0; u8 pcnt = 0; u8 nchar; strtemp = str; while (*strtemp != '\0') { if (*strtemp != ' ' && (pcnt & 0X7F) < 5) { if (pcnt == 0) pcnt |= 0X80; if (((pcnt & 0x7f) == 4) && (*strtemp != '*')) break; fpname[pcnt & 0x7f] = *strtemp; pcnt++; } else if (pcnt == 0X85) break; strtemp++; } if (pcnt) { fpname[pcnt & 0x7f] = '\0'; if (usmart_strcmp(fpname, "void") == 0) *rval = 0; else *rval = 1; pcnt = 0; } res = 0; strtemp = str; while (*strtemp != '(' && *strtemp != '\0') { strtemp++; res++; if (*strtemp == ' ' || *strtemp == '*') { nchar = usmart_search_nextc(strtemp); if (nchar != '(' && nchar != '*') offset = res; } } strtemp = str; if (offset) strtemp += offset + 1; res = 0; nchar = 0; while (1) { if (*strtemp == 0) { res = USMART_FUNCERR; break; } else if (*strtemp == '(' && nchar == 0) fover++; else if (*strtemp == ')' && nchar == 0) { if (fover) fover--; else res = USMART_FUNCERR; if (fover == 0) break; } else if (*strtemp == '"') nchar = !nchar;
if (fover == 0) { if (*strtemp != ' ') { *fname = *strtemp; fname++; } } else { if (*strtemp == ',') { temp = 1; pcnt++; } else if (*strtemp != ' ' && *strtemp != '(') { if (pcnt == 0 && fplcnt < 5) { fpname[fplcnt] = *strtemp; fplcnt++; } temp++; } if (fover == 1 && temp == 2) { temp++; parmnum++; } } strtemp++; } if (parmnum == 1) { fpname[fplcnt] = '\0'; if (usmart_strcmp(fpname, "void") == 0) parmnum = 0; } *pnum = parmnum; *fname = '\0'; return res; }
|
u8 usmart_strcmp(u8 *str1, u8 *str2)
比较两个字符串是不是一样, 和strcmp类似
1 2 3 4 5 6 7 8 9 10 11 12 13
| u8 usmart_strcmp(u8 *str1, u8 *str2) { while (1) { if (*str1 != *str2) return 1; if (*str1 == '\0') break; str1++; str2++; } return 0; }
|
u8 usmart_search_nextc(u8 *str)
1 2 3 4 5 6 7 8 9 10
|
u8 usmart_search_nextc(u8 *str) { str++; while (*str == ' ' && str != '\0') str++; return *str; }
|
usmart_init—-初始化
初始化定时器, 使用的是定时器4, 主频也就是sysclk是72mhz, sysclk100-1是分频系数—> 72000000/(72 * 100-1 +1 )=10000hz, 所以一个定时器周期是1/10000==0.0001s==0.1ms, 定时器0.1ms1000====100ms中断一次
1
| Timer4_Init(1000, (u32)sysclk * 100 - 1);
|
usmart_cmd_rec—-识别
usmart_cmd_rec函数逻辑
入口参数是从串口接收到的函数名字, 字符串指针
首先通过usmart_get_fname得到函数名字和参数个数
然后从0到usmart_dev.fnum(结构体里函数数量值)开始循环, strcmp逐个比较接收的函数名字和本地存储的函数名字
情况1. 如果找到一样的,判断收到的函数参数是不是和存储的函数参数个数相等
情况1.1 收到的小于存储的就返回错误USMART_PARMERR, 记下函数id, 跳出循环
情况1.2 收到的大于存储的, xxxxxxxxxxx
情况1.3 收到的等于存储的, 用usmart_get_fparam获得函数参数个数并赋值给usmart_dev.pnum
情况3. 如果i循环到等于usmart_dev.fnum, 也就是全部找完了, 没有发现符合的函数名字,也返回一个错误USMART_NOFUNCFIND
都判断完,找到了且参数个数也一样就返回USMART_OK
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| u8 usmart_cmd_rec(u8 *str) { u8 sta, i, rval; u8 rpnum, spnum; u8 rfname[MAX_FNAME_LEN]; u8 sfname[MAX_FNAME_LEN]; sta = usmart_get_fname(str, rfname, &rpnum, &rval); if (sta) return sta; for (i = 0; i < usmart_dev.fnum; i++) { sta = usmart_get_fname((u8 *)usmart_dev.funs[i].name, sfname, &spnum, &rval); if (sta) return sta; if (usmart_strcmp(sfname, rfname) == 0) { if (spnum > rpnum) return USMART_PARMERR; usmart_dev.id = i; break; } } if (i == usmart_dev.fnum) return USMART_NOFUNCFIND; sta = usmart_get_fparam(str, &i); if (sta) return sta; usmart_dev.pnum = i; return USMART_OK; }
u8 usmart_get_fname(u8 *str, u8 *fname, u8 *pnum, u8 *rval)
|
usmart_exe—-执行
usmart_scan—-扫描
整体逻辑
- 初始化定时器四, 0.1ms产生一次中断, 执行usmart_scan进行扫描
- 扫描成功后执行usmart_cmd_rec识别接收的字符串
- 识别成功后执行usmart_exe运行函数