命令语言解析 - 如何正式获取? [英] Command language parsing - how formal to get?

查看:73
本文介绍了命令语言解析 - 如何正式获取?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗨:


为TMS320F2812完成足够的串口驱动程序代码后,微控制器与终端通话,我现在正在尝试不同的

接近命令解释。


我有一个非常简单的命令集,包含几个不带参数的单个字母

命令。一些额外的单个字母

命令带参数:


命令语言(有点概括):


命令参数(s)描述


a do action_a

b do action_b

c do action_c

...

n do action_n

...

y [var_name] display variable(s)

z var_name value set variable to value


其中var_name是变量标识符。 ''''命令允许一个

显示由var_name标识的变量的值。如果未提供var_name

,则此命令将显示所有变量。 e命令

允许将var_name标识的变量的值设置为value。


目前我使用的是最简单但最不灵活的解析方法

命令。我在运行中进行扫描和词法分析,并使用if,否则,如果,

其他逻辑块进行解析。 (我知道,可悲。)这种方法需要

如果,否则if,else阻止命令语言的每个字段。


接下来我打算将词法分析拆分为第一遍,并创建一个

的令牌列表,并进行其他处理,例如将关键字转换为关键字和变量名称以及数字文本字段机器上的数字。

这将消除扫描/ lexing,使

解析代码更具可读性。


然后第二遍解析仍然可以使用if,否则如果,

否则看起来似乎语言有一个固定且相对较小的b $ b小的最大数字每个命令的字段数。


问题是,对于与上述类似的语言和

考虑以下因素:


1.需要在嵌入式微控制器中实现不超过一美元的程序内存K / b
2.不是特别高的sp需要进行解析。 Ccommands将通过115.2kbps的慢速接口间歇性地发出


3.易于理解和调整代码以适应命令的变化

套是非常有价值的。最有可能的补充是告诉

接受表示存储在uC RAM中的文件/表格为/ b $ b的二进制数据流的命令。


使用if,else if,else block或

进行硬编码解析通常会决定使用更通用的技术,例如

正式化BNR形式的语言描述,并使用词法分析器/解析器

生成工具,如lex / yacc?


我总是找到主题解析器/口译员/编译器

引人入胜,并希望花大量时间了解更多

。然而,我还必须让事情发挥作用。我觉得

就像我最终需要用

不同的解析技术进行相当多的实验来感受最好的选择方法

这个和将来的应用程序。


感谢您的投入。

-

美好的一天!


________________________________________

Christopher R. Carlen

首席激光与电子技师

美国加州桑迪亚国家实验室
< a href =mailto:cr *************** @ BOGUSsandia.gov> cr *************** @ BOGUSsandia.gov

注意,删除文本:RemoveThis和

" BOGUS"从电子邮件地址到回复。

Hi:

Having completed enough serial driver code for a TMS320F2812
microcontroller to talk to a terminal, I am now trying different
approaches to command interpretation.

I have a very simple command set consisting of several single letter
commands which take no arguments. A few additional single letter
commands take arguments:

Command language (somewhat generalized):

command argument(s) description

a do action_a
b do action_b
c do action_c
...
n do action_n
...
y [var_name] display variable(s)
z var_name value set variable to value

where var_name is a variable identifier. The ''d'' command lets one
display the value of a variable identified by var_name. If no var_name
is provide, this command will display all variables. The ''e'' command
lets one set the value of the variable identified by var_name to value.

Presently I am using the simplest yet least flexible approach to parse
commands. I scan and lexically analyze on the fly, and use if, else if,
else logic blocks to parse. (I know, pathetic.) This approach requires
one if, else if, else block for each field of the command language.

Next I plan to split the lexical analysis to a first-pass, and create a
list of tokens, with additional processing such as converting keywords
and variable names to keys, and numeric text fields to machine numbers.
This will eliminate the scanning/lexing on the fly to make the
parsing code much more readable.

Then a second pass of parsing could still be done using if, else if,
else it seems in the case that a language has a fixed and relatively
small maximum number of fields per command.

The question is then, for a language similar to the above and
considering these factors:

1. need to implement in an embedded microcontroller in not more than a
few K of program memory
2. not a particularly high speed of parsing is required. Ccommands will
be issued intermittently over a slow interface of perhaps 115.2kbps.
3. ease of understanding and adapting the code to changes in the command
set is very valuable. Most likely additions would be a command to tell
the thing to accept a binary data stream representing a file/table to be
stored in the uC RAM.

Is it common to hardcode parsing with if, else if, else blocks or at
what point does one decide to use more generalized techniques such as
formalizing the language description in BNR form, and using lexer/parser
generation tools such as lex/yacc ?

I have always found the topic of parsers/interpreters/compilers
fascinating, and would like to spend considerable time learning more
about this. Yet I also have to "just get the thing to work." I feel
like I will ultimately need to perform quite a few experiments with
different parsing techniques to get a feel for the best method to choose
for this and future applications.

Thanks for input.
--
Good day!

________________________________________
Christopher R. Carlen
Principal Laser&Electronics Technologist
Sandia National Laboratories CA USA
cr***************@BOGUSsandia.gov
NOTE, delete texts: "RemoveThis" and
"BOGUS" from email address to reply.

推荐答案

2007年8月10日星期五10:12:50 -0700,Chris Carlen

< cr *************** @ BOGUSsandia.govwrote:
On Fri, 10 Aug 2007 10:12:50 -0700, Chris Carlen
<cr***************@BOGUSsandia.govwrote:

>完成了足够的串行驱动程序代码TMS320F2812单片机与终端通话,我现在正在尝试不同的命令解释方法。

我有一个非常简单的命令集,由几个单字组成
不带参数的命令。一些额外的单个字母
命令带有参数:

命令语言(有点概括):

命令参数描述

a action_a
b做action_b
c做action_c

...
n做action_n

...
y [var_name] display variable(s)
z var_name value set variable to value

其中var_name是变量标识符。 d命令允许一个显示由var_name标识的变量的值。如果未提供var_name
,则此命令将显示所有变量。 ''''命令
允许将var_name标识的变量的值设置为value。

目前我使用最简单但最不灵活的方法来解析
命令。我在运行中扫描和词法分析,并使用if,否则,如果,
else逻辑块进行解析。 (我知道,可悲。)这种方法需要
一个if,否则if,else阻止命令语言的每个字段。

接下来我打算将词法分析分成第一个 - 传递,并创建一个令牌列表,并进行额外处理,例如将关键字
和变量名转换为键,将数字文本字段转换为机器号。

这将消除动态扫描/ lexing以使解析代码更具可读性。

然后第二遍解析仍然可以使用if,否则如果,
似乎如果一种语言每个命令具有固定且相对较小的最大字段数。

那么问题是,对于类似于上述的语言而言,考虑到这些因素:

1。需要在嵌入式微控制器中实现不超过几K的程序存储器2。不需要特别高的解析速度。 Ccommands将通过115.2kbps的慢速接口间歇性地发布。
3。易于理解和调整代码以适应命令的变化
设置非常有价值。很可能添加的是一个命令,告诉接受表示存储在uC RAM中的文件/表的二进制数据流。

它是否常见用if,else if,else阻塞或在什么时候决定使用更通用的技术来解析硬编码,例如以BNR形式形式化语言描述,以及使用词法分析器/解析器生成像lex / yacc这样的工具?

我总是发现解析器/解释器/编译器的主题很吸引人,并且想花很多时间学习更多关于这个的知识。然而,我还必须让事情发挥作用。我觉得我最终需要用不同的解析技术进行相当多的实验,以便为这个和未来的应用程序选择最好的方法。
<感谢您的意见。
>Having completed enough serial driver code for a TMS320F2812
microcontroller to talk to a terminal, I am now trying different
approaches to command interpretation.

I have a very simple command set consisting of several single letter
commands which take no arguments. A few additional single letter
commands take arguments:

Command language (somewhat generalized):

command argument(s) description

a do action_a
b do action_b
c do action_c
...
n do action_n
...
y [var_name] display variable(s)
z var_name value set variable to value

where var_name is a variable identifier. The ''d'' command lets one
display the value of a variable identified by var_name. If no var_name
is provide, this command will display all variables. The ''e'' command
lets one set the value of the variable identified by var_name to value.

Presently I am using the simplest yet least flexible approach to parse
commands. I scan and lexically analyze on the fly, and use if, else if,
else logic blocks to parse. (I know, pathetic.) This approach requires
one if, else if, else block for each field of the command language.

Next I plan to split the lexical analysis to a first-pass, and create a
list of tokens, with additional processing such as converting keywords
and variable names to keys, and numeric text fields to machine numbers.
This will eliminate the scanning/lexing on the fly to make the
parsing code much more readable.

Then a second pass of parsing could still be done using if, else if,
else it seems in the case that a language has a fixed and relatively
small maximum number of fields per command.

The question is then, for a language similar to the above and
considering these factors:

1. need to implement in an embedded microcontroller in not more than a
few K of program memory
2. not a particularly high speed of parsing is required. Ccommands will
be issued intermittently over a slow interface of perhaps 115.2kbps.
3. ease of understanding and adapting the code to changes in the command
set is very valuable. Most likely additions would be a command to tell
the thing to accept a binary data stream representing a file/table to be
stored in the uC RAM.

Is it common to hardcode parsing with if, else if, else blocks or at
what point does one decide to use more generalized techniques such as
formalizing the language description in BNR form, and using lexer/parser
generation tools such as lex/yacc ?

I have always found the topic of parsers/interpreters/compilers
fascinating, and would like to spend considerable time learning more
about this. Yet I also have to "just get the thing to work." I feel
like I will ultimately need to perform quite a few experiments with
different parsing techniques to get a feel for the best method to choose
for this and future applications.

Thanks for input.



克里斯。只是一些评论。


(1)

我不会像你那样设计命令和查询。我喜欢IEEE-488-2的

推荐。其中一个是使用?查询

并使用也可以解析的命令回复此类查询。


例如,在上面的列表中,列出''y ''和''z''用于阅读和

设置变量值。建议的程序是使用

两个动作的相同文本,但是这样:


var? foo


会引起以下回复:


var foo 5.3


和你' 'd'说:


var foo 7


把它改为7.


查询表单只是一个?添加到命令表单的末尾,用

换句话说。


它还建议你实现一个简单的命令

转出当前状态。该状态应该以这样的方式列出,如果它的接收器只是将整个身体直接发送回你的设备,它将具有恢复的效果。状态。

因此,如果您有三个变量代表您设备中所有重要的

状态,请将它们称为S1,S2和S3,然后某人可能

发出以下查询:


州?


并得到以下回复:


var S1 4.1

var S2 6.5

var S3 -1.2

如果接收者然后解雇那些直接回来,状态

(无论以前是什么)将恢复到这些值。


(2)

这里是一个可以考虑的选项:


for(;;){

auto void(* func)(const char * cmd);

auto int status;

static char commandname [MAXCOMMANDNAME];

skipwhitespace();

parsecmd(commandn如果((func = commandsearch(commandname))!= 0)

status =(* func)(command);

否则

status = NOSUCHCOMMAND;

if(status!= SUCCESS){

skipremainderofline();

/ *在这里打印某种解析错误* /

}

}


单独这些行。 ''parsecmd''函数可能使用你已经拥有的

if..else结构。我倾向于使用一个表来列出每个命令/查询的文本以及一个指向

函数的函数指针来调用其余的解析和执行。因为遗产原因,我曾经想过为了同样的效果而给b $ b有几个命令/查询名称。

这样做很容易。


无论如何,只是想一想。


(3)

我不知道你是否打算在解析时做其他事情。在我做的大多数事情中,当我还有其他的工作时,我不会被卡住,嵌套在一些

解析代码中是至关重要的。需要监控。对于

示例,我可能需要在按钮的基础上采取行动

也可能在大约同一时间按下我正在解析串行

端口文本。并且我不能坐在那里等待命令的下一个

字符,代码埋在一些

if..else的中间,而有一个按键也需要注意

现在。


所以我几乎总是包含一些操作的内容

系统,这里。在许多情况下,这可能仅仅是实现具有switchaway()函数的协作任务开关。

换句话说,如果我在中间串口代码,埋在一个if..else里面的
,我现在把串口代码叫做

"获取下一个字符"并且它回应说还没有更多

字符......然后我称之为switchaway()函数。当

它返回时,我被允许多一些时间,所以我重新调用串行端口

代码用于该下一个字符的事情。如果它仍然是空的,我再次回想起switchaway()函数。

。等等。这样,我在解析代码中间不会丢失我的位置,但同时我可以将b $ b传递给其他函数,这样他们就可以了可以完成他们的工作。


顺便说一句,实现

这样的功能并不需要多行汇编代码。大多数编译器只留出几个需要在函数调用中保存的
寄存器,所以

它只需要推几个寄存器,切换到新的堆栈指针,

然后弹出相同的寄存器并返回。而已。所以它不是很难b $ b,它有助于保持代码清洁。否则,你必须以某种方式保存你的解析函数的状态,从它返回所以

其他工作可以完成,然后以某种方式将你自己倒回到一些

下次你在它的顶部被调用时讨厌的位置。或者只是

坐在那里,在等待下一个

串口字符到达时忽略其他所有内容。


最好的好运,

Jon

Hi, Chris. Just a few comments.

(1)
I wouldn''t design the commands and queries as you did. I like the
recommendations of IEEE-488-2. One of them is to use a ? for queries
and to reply to such queries with a command that can also be parsed.

For example, in your above list, you list ''y'' and ''z'' for reading and
setting variable values. The recommended procedure would be to use
the same text for both actions, but in this way:

var? foo

which would cause the following reply:

var foo 5.3

and you''d say:

var foo 7

to change it to 7.

The query form is just a ? added to the end of a command form, in
other words.

It also recommends that you implement a single, simple command that
dumps out the current state. That state should be listed out in such
a way that if the receiver of it simply sent the entire body straight
back to your device, it would have the effect of restoring the state.
So if you had three variables that represented all of the important
state in your device, call them S1, S2, and S3, then someone might
issue the following query:

state?

and get the following response:

var S1 4.1
var S2 6.5
var S3 -1.2

and that if the receiver then fired those straight back in, the state
(no matter what it was before) would be restored to those values.

(2)
Here''s an option to consider:

for ( ; ; ) {
auto void (*func)( const char * cmd );
auto int status;
static char commandname[MAXCOMMANDNAME];
skipwhitespace( );
parsecmd( commandname, MAXCOMMANDNAME );
if ( (func= commandsearch( commandname )) != 0 )
status= (*func)( command );
else
status= NOSUCHCOMMAND;
if ( status != SUCCESS ) {
skipremainderofline( );
/* print some kind of parsing error here */
}
}

Something alone these lines. The ''parsecmd'' function might use the
if..else structure you already have. I tend to use a table that lists
the text of each command/query along with a function pointer to the
function to call for the rest of the parsing and execution. There
have been times in my life when, for legacy reasons, I''ve wanted to
have several command/query names for the same effect, for example, and
this makes that pretty easy to do.

Anyway, just a thought.

(3)
I don''t know if you intend to do other things, while parsing. In most
stuff I do, it''s essential that I don''t get stuck, nested down in some
parsing code, when there is other work that also needs monitoring. For
example, I may need to take action on the basis of a push button that
might also be pressed at about the same time I''m down parsing serial
port text. And I can''t afford to sit around waiting for the next
character of a command, with the code buried in the middle of some
if..else, while there is a keypress that is also demanding attention
right now.

So I almost always include something along the lines of an operating
system, here. In many cases, this might be nothing more than just
implementing cooperating task switches with a switchaway() function.
In other words, if I''m in the middle of the serial port code, buried
down inside an if..else, and I''m now calling the serial port code to
"get the next character" and it responds that there are no more
characters just yet... then I call this switchaway() function. When
it returns, I''m allowed some more time so I re-call the serial port
code for that ''next character'' thing. If it is still empty, I recall
the switchaway() function, again. And so on. That way, I don''t lose
my place in the middle of my parsing code but at the same time I can
pass along the cpu to other functions so they can get their work done.

It doesn''t take more than a few lines of assembly code to implement
such a function, by the way. Most compilers set aside only a few
registers that need to be saved across a function call like that, so
it only needs to push a few registers, switch to a new stack pointer,
and then pop the same registers and return. That''s it. So it isn''t
hard and it helps keep your code clean. Otherwise, you''d have to
somehow save the state of your parsing function, return from it so
other work can get done, then somehow rewind yourself back into some
nasty position the next time you get called at the top of it. Or just
sit there and ignore everything else while you wait for the next
serial port character to arrive.

Best of luck,
Jon


在文章< f9 ******** @ news4.newsguy.com>中,Chris Carlen说...
In article <f9********@news4.newsguy.com>, Chris Carlen says...

嗨:


已经为TMS320F2812完成了足够的串行驱动程序代码

微控制器与终端通话,我现在尝试不同的方法来解释命令。


我有一个非常简单的命令集,由几个单字母组成

命令不带参数。一些额外的单个字母

命令带参数:
Hi:

Having completed enough serial driver code for a TMS320F2812
microcontroller to talk to a terminal, I am now trying different
approaches to command interpretation.

I have a very simple command set consisting of several single letter
commands which take no arguments. A few additional single letter
commands take arguments:



对于一个简单的人(而不是机器)接口,我经常使用一个

简单的查找表,由命令名/函数指针对组成。

简单的强力查找,你可以为每个添加一个简单的帮助字符串

命令。函数本身负责解析任何

参数。


简单但有限。


Robert


-

通过 http://www.teranews.com

For a simple human (as opposed to machine) interface I''ve often used a
simple lookup table composed of command name/function pointer pairs.
Simple brute force lookup, and you can add a simple help string for each
command. The functions themselves were responsible for parsing any
arguments.

Simple but limited.

Robert

--
Posted via a free Usenet account from http://www.teranews.com


Jonathan Kirwan写道:
Jonathan Kirwan wrote:

周五,2007年8月10日10:12:50 -0700,Chris Carlen

< cr *************** @ BOGUSsandia.govwrote :
On Fri, 10 Aug 2007 10:12:50 -0700, Chris Carlen
<cr***************@BOGUSsandia.govwrote:

>> [edit]
命令语言(略有概括):

命令参数说明

a action_a
b做action_b
c做action_c
...
n做action_n
...
y [var_name]显示变量
z var_name value将变量设置为值

问题是,对于与上述类似的语言,并考虑以下因素:

1。需要在嵌入式微控制器中实现不超过几K的程序存储器2。不需要特别高的解析速度。 Ccommands将通过115.2kbps的慢速接口间歇性地发布。
3。易于理解和调整代码以适应命令的变化
设置非常有价值。最有可能的补充是告诉接受表示存储在uC RAM中的文件/表的二进制数据流的命令。
[edit]
>>[edit]
Command language (somewhat generalized):

command argument(s) description

a do action_a
b do action_b
c do action_c
...
n do action_n
...
y [var_name] display variable(s)
z var_name value set variable to value
[edit]
The question is then, for a language similar to the above and
considering these factors:

1. need to implement in an embedded microcontroller in not more than a
few K of program memory
2. not a particularly high speed of parsing is required. Ccommands will
be issued intermittently over a slow interface of perhaps 115.2kbps.
3. ease of understanding and adapting the code to changes in the command
set is very valuable. Most likely additions would be a command to tell
the thing to accept a binary data stream representing a file/table to be
stored in the uC RAM.
[edit]



克里斯。只是一些评论。


(1)

我不会像你那样设计命令和查询。我喜欢IEEE-488-2的

推荐。其中一个是使用?查询

并使用也可以解析的命令回复此类查询。


例如,在上面的列表中,列出''y ''和''z''用于阅读和

设置变量值。建议的程序是使用

两个动作的相同文本,但是这样:


var? foo


会引起以下回复:


var foo 5.3


和你' 'd'说:


var foo 7


把它改为7.


查询表单只是一个?添加到命令表单的末尾,用

换句话说。


Hi, Chris. Just a few comments.

(1)
I wouldn''t design the commands and queries as you did. I like the
recommendations of IEEE-488-2. One of them is to use a ? for queries
and to reply to such queries with a command that can also be parsed.

For example, in your above list, you list ''y'' and ''z'' for reading and
setting variable values. The recommended procedure would be to use
the same text for both actions, but in this way:

var? foo

which would cause the following reply:

var foo 5.3

and you''d say:

var foo 7

to change it to 7.

The query form is just a ? added to the end of a command form, in
other words.



感谢您的意见。


有趣的建议。我想,因为我有0个设计命令语言的经验,所以大多数建议看起来很有趣:-)


实际上,我已经从这个命令集中汲取了灵感来自DOS调试。

我也在用Python写一个十六行编辑器(作为Python学习

练习),它也使用这个单字母业务。


我刚下载了IEEE-488.2好悲伤!我经常回避

标准,因为它们总是很长并且很难阅读。为了熟悉这个,我们需要花费几个月的时间。所以我没有兴趣制作完全符合488标准的小工具

。看起来你好像不是你想要的那样。


我曾想过要熟悉SCPI,看看它是不是

也适用于该项目。它似乎太复杂了。

Thanks for the input.

Interesting suggestion. I suppose since I have 0 experience with
designing command languages, most suggestinos will seem interesting :-)

Actually, I have taken inspiration for this command set from DOS debug.
I''m also writing a hex line editor in Python (as a Python learning
exercise) which also uses this single letter business.

I just downloaded IEEE-488.2 Good grief! I have often shyed away from
standards since they are always long and agonizing to read. Would take
months just to get familiar with this. So I have no interest in making
the gadget fully 488 compliant. It doesn''t appear that you were
implying that I should.

I had thought about becoming familiar with SCPI to see if it would be
applicable to this project as well. It just all seems way too complicated.


它还建议你实现一个简单的命令,即
转出当前状态。该状态应该以这样的方式列出,如果它的接收器只是将整个身体直接发送回你的设备,它将具有恢复的效果。状态。

因此,如果您有三个变量代表您设备中所有重要的

状态,请将它们称为S1,S2和S3,然后某人可能

发出以下查询:


州?


并得到以下回复:


var S1 4.1

var S2 6.5

var S3 -1.2

如果接收者然后解雇那些直接回来,状态

(无论以前是什么)将恢复到这些值。
It also recommends that you implement a single, simple command that
dumps out the current state. That state should be listed out in such
a way that if the receiver of it simply sent the entire body straight
back to your device, it would have the effect of restoring the state.
So if you had three variables that represented all of the important
state in your device, call them S1, S2, and S3, then someone might
issue the following query:

state?

and get the following response:

var S1 4.1
var S2 6.5
var S3 -1.2

and that if the receiver then fired those straight back in, the state
(no matter what it was before) would be restored to those values.



这很酷。

This is pretty cool.


(2)

这里'可以选择考虑:


for(;;){

auto void(* func)(const char * cmd);

auto int status;

static char commandname [MAXCOMMANDNAME];
(2)
Here''s an option to consider:

for ( ; ; ) {
auto void (*func)( const char * cmd );
auto int status;
static char commandname[MAXCOMMANDNAME];



命令名将由parsecmd()填充命令关键字?

commandname will get filled with a command keyword by parsecmd()?


skipwhitespace();

parsecmd(commandname,MAXCOMMANDNAME);
skipwhitespace( );
parsecmd( commandname, MAXCOMMANDNAME );



parsecmd()基本上是一个提取下一个单词的词法分析器?

parsecmd() is basically a lexer which extracts the next word ?


if((func = commandsearch(commandname))!= 0)

status =(* func)(command);
if ( (func= commandsearch( commandname )) != 0 )
status= (*func)( command );



查找并执行一个函数来执行该命令的操作。

Lookup and execute a function to perform the action of that command.


else

status = NOSUCHCOMMAND;
else
status= NOSUCHCOMMAND;


if(status!= SUCCESS){

skipremainderofline();

/ *在这里打印某种解析错误* /

}

}

单独这些行。 ''parsecmd''函数可能使用你已经拥有的

if..else结构。我倾向于使用一个表来列出每个命令/查询的文本以及一个指向

函数的函数指针来调用其余的解析和执行。因为遗产原因,我曾经想过为了同样的效果而给b $ b有几个命令/查询名称。

这样做很容易。

无论如何,只是想一想。
if ( status != SUCCESS ) {
skipremainderofline( );
/* print some kind of parsing error here */
}
}
Something alone these lines. The ''parsecmd'' function might use the
if..else structure you already have. I tend to use a table that lists
the text of each command/query along with a function pointer to the
function to call for the rest of the parsing and execution. There
have been times in my life when, for legacy reasons, I''ve wanted to
have several command/query names for the same effect, for example, and
this makes that pretty easy to do.
Anyway, just a thought.



需要相当多的考虑。我会得到你的代码所做的。

只是有点模糊。我想我可以在这里提出很多想法。

It will take considerable thought. I sort of get what your code does.
Just a little vague. I think I can come up with lots of ideas here, though.


(3)

我不知道你是否打算在解析时做其他事情。在我做的大多数事情中,当我还有其他的工作时,我不会被卡住,嵌套在一些

解析代码中是至关重要的。需要监控。对于

示例,我可能需要在按钮的基础上采取行动

也可能在大约同一时间按下我正在解析串行

端口文本。并且我不能坐在那里等待命令的下一个

字符,代码埋在一些

if..else的中间,而有一个按键也需要注意

现在。


所以我几乎总是包含一些操作的内容

系统,这里。在许多情况下,这可能仅仅是实现具有switchaway()函数的协作任务开关。

换句话说,如果我在中间串口代码,埋在一个if..else里面的
,我现在把串口代码叫做

"获取下一个字符"并且它回应说还没有更多

字符......然后我称之为switchaway()函数。当

它返回时,我被允许多一些时间,所以我重新调用串行端口

代码用于该下一个字符的事情。如果它仍然是空的,我再次回想起switchaway()函数。

。等等。这样,我在解析代码中间不会丢失我的位置,但同时我可以将b $ b传递给其他函数,这样他们就可以了可以完成他们的工作。


顺便说一句,实现

这样的功能并不需要多行汇编代码。大多数编译器只留出几个需要在函数调用中保存的
寄存器,所以

它只需要推几个寄存器,切换到新的堆栈指针,

然后弹出相同的寄存器并返回。而已。所以它不是很难b $ b,它有助于保持代码清洁。否则,你必须以某种方式保存你的解析函数的状态,从它返回所以

其他工作可以完成,然后以某种方式将你自己倒回到一些

下次你在它的顶部被调用时讨厌的位置。或者只是

坐在那里,在等待下一个

串口字符到达时忽略其他所有内容。
(3)
I don''t know if you intend to do other things, while parsing. In most
stuff I do, it''s essential that I don''t get stuck, nested down in some
parsing code, when there is other work that also needs monitoring. For
example, I may need to take action on the basis of a push button that
might also be pressed at about the same time I''m down parsing serial
port text. And I can''t afford to sit around waiting for the next
character of a command, with the code buried in the middle of some
if..else, while there is a keypress that is also demanding attention
right now.

So I almost always include something along the lines of an operating
system, here. In many cases, this might be nothing more than just
implementing cooperating task switches with a switchaway() function.
In other words, if I''m in the middle of the serial port code, buried
down inside an if..else, and I''m now calling the serial port code to
"get the next character" and it responds that there are no more
characters just yet... then I call this switchaway() function. When
it returns, I''m allowed some more time so I re-call the serial port
code for that ''next character'' thing. If it is still empty, I recall
the switchaway() function, again. And so on. That way, I don''t lose
my place in the middle of my parsing code but at the same time I can
pass along the cpu to other functions so they can get their work done.

It doesn''t take more than a few lines of assembly code to implement
such a function, by the way. Most compilers set aside only a few
registers that need to be saved across a function call like that, so
it only needs to push a few registers, switch to a new stack pointer,
and then pop the same registers and return. That''s it. So it isn''t
hard and it helps keep your code clean. Otherwise, you''d have to
somehow save the state of your parsing function, return from it so
other work can get done, then somehow rewind yourself back into some
nasty position the next time you get called at the top of it. Or just
sit there and ignore everything else while you wait for the next
serial port character to arrive.



我的小工具上有两个关键线程,一个非关键线程

这是串行接口。排名第一的优先级是

非抢占,定时器中断驱动的周期性线程。保证在某个有限的最长时间内完成,但是它的周期可以根据可能受用户影响的参数而变化。

界面。基本上,它是一个波形合成器,具有可变的
时钟周期。它有一个最大时钟频率。关于


接下来是#2,一个preemptable(由顶级线程)周期性线程,它是

也是定时器中断驱动的。第二个有一个简短的汇编介绍

尽快重新启用中断,这样它就不会阻止#1超过几个周期的
。这是硬件用户界面(面板按钮)

轮询线程。它可以容忍被#1砍掉。它还有一个

有限的最大执行时间。


因此,串行代码可以根据需要阻止。

唯一重要的是它不会阻塞自身足够长的时间,以至于在FIFO溢出之前无法清除串行接收FIFO。


我计划使用所有内容的最大执行时间及其

周期来计算设备的最大波特率

在确定永远不会错过角色时收到。至少我认为

这可以确定。


这就是我的操作系统。只有几个线程,很容易让定时器

触发重要的线程,然后绕过其余部分。

-

美好的一天!


________________________________________

Christopher R. Carlen

首席激光与电子技师

美国加州桑迪亚国家实验室
cr ********* ******@BOGUSsandia.gov

注意,删除文本:RemoveThis和

" BOGUS"从电子邮件地址到回复。

I have two critical threads on my gadget, and a non-critical thread
which is the serial interface. The top #1 priority is a
non-preemptable, timer interrupt driven periodic thread. It is
guaranteed to finish in some finite maximum time, but it''s period can
vary according to parameters which can be influenced by the user
interface. Basically, it''s a waveform synthesizer with variable
clocking period. It''s got a max clocking freq. of about

Next is #2, a preemptable (by the top thread) periodic thread which is
also timer interrupt driven. This second one has a brief assembly intro
which reenables interrupts ASAP so that it can''t block #1 for more than
a few cycles. This is the hardware user interface (panel buttons)
polling thread. It can tolerate being chopped up by #1. It also has a
finite maximum exec time.

Thus, the serial code can block for as long as it likes. The only thing
that matters is that it doesn''t block itself long enough to fail to
clear out the serial receive FIFO before the FIFO overflows.

I plan to use the maximum exec times for all the stuff and their
periodicities to compute the maximum baud rate at which the device can
receive while being certain never to miss characters. At least I think
this can be determined.

So that''s my OS. With only a few threads, it''s easy to just let timers
trigger the important ones, and round-robin the rest.
--
Good day!

________________________________________
Christopher R. Carlen
Principal Laser&Electronics Technologist
Sandia National Laboratories CA USA
cr***************@BOGUSsandia.gov
NOTE, delete texts: "RemoveThis" and
"BOGUS" from email address to reply.


这篇关于命令语言解析 - 如何正式获取?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆