嗯。众所周知,最近我在研究CodeWarrior的调试器HIWAVE,发现了很多有意思的特性。
这次就总结下调试器提供的Terminal控件,以及怎么使用它与Full Chip Simulation模式下模拟出来的芯片进行通讯/交互。
作者注:作者博客(http://blog.csdn.net/lin_strong),转载请保留此条。请勿用于商业用途。
Terminal控件
先简单介绍下Terminal控件。
界面及菜单
Ternimal(终端)是HIWAVE调试器提供的一个用于模拟输入输出的控件,或者说是用于重定向输入输出的可能更准确点。
通过 菜单栏Component->Open->Terminal 来打开它。
图 1.Terminal界面
在其上点鼠标右键弹出上下文菜单:
图 2.Terminal上下文菜单
重定向配置
其他先不讲,先点击Configure Connections这个选项配置连接。
图 3.Configure Terminal Connections界面
默认的是Virtual SCI这个配置,可以点开下拉框选择其他配置,或者自己定制。
而底下那个列表框是什么意思呢? 里头显示的是当前的重定向配置。
像图中 Input File –> Virtual SCI的意思就是输入文件会被重定向到 虚拟SCI端口。再直白点就是,如果我打开了一个输入文件,那它其中的内容就会被不断发送到虚拟SCI中去直到文件结束。上下文菜单中的Input File和Output File就是干这个用的。
所以这个配置的作用就是,把键盘的输入以及输入文件的输入都发送到虚拟SCI端口去,而虚拟SCI的输入则会发送到终端的界面 以及 输出文件(如果打开了的话)中。
除了这三个外还可以使用电脑上的串行端口(Serial Port)。
于是就可以组合来做各种各样的事情了,比如我可以把键盘输入重定向到界面以及输出文件中去,这样就把Ternimal用成了个简易的文本编辑器了,当然这个文本编辑器的功能很受限,只能不断往后输入,不能撤销,不能回车,不能一大堆事情。
通过数据流控制
Ternimal还提供了一个特性,可以使用来自虚拟SCI口或串口的数据流来打开/关闭文件,注意,来自键盘或文件的数据流是不能使用这一特性的,并且这特性只在有包含输入文件或输出文件的链接时有用。
表一是控制命令对应的逃逸字符串序列以及其对应的功能。其中,filename是由一个控制字符(如 CR)结尾并且有效的文件名。ESC是ESC字符(对应ASCII码27(十进制))。
表 1.终端文件控制命令
逃逸字符串序列 | 功能 |
---|---|
ESC “h” “1” | 关闭输出文件。 |
ESC “h” “2” filename | 打开输出文件。 |
ESC “h” “3” filename | 打开输出文件并阻止到终端界面的输出。 |
ESC “h” “4” | 关闭输入文件。 |
ESC “h” “5” filename | 打开输入文件。 |
ESC “h” “6” filename | 附加到现存的输出文件. |
ESC “h” “7” filename | 附加到现存的输出文件并阻止到终端界面的输出. |
.
所以待会你在terminal.c 文件中看到TERM_Direct这个函数的时候再对照一下这个表,就会焕然大悟了。
虚拟SCI
好了,讲完了terminal,接下来就要说这个虚拟SCI的事了。我们与仿真芯片的通讯方式本质上就是通过Terminal控件与仿真芯片提供的虚拟SCI模块进行通讯。
上位机配置
使用虚拟SCI时,Terminal会访问全芯片仿真的对象池的Sci0对象(默认配置下)。按照手册的说法:
为了终端控件能以默认配置工作,目标必须提供一个名为Sci0的对象。如果找不到Sci0对象,则无法进行通讯。……只有一些特定的全芯片仿真直接提供了Sci0这个对象,对于没有提供的那些,需要用户自己定义Sci0对象并装载指定的寄存器名。
你可以通过Inspect控件来查看你当前这个设备有没有Sci0这个对象。另外还可以修改配置来访问非Sci0的对象。具体细节就不多说了,反正对于我用的MC9S12XEP100来说,它是有定义Sci0这个对象的。所以直接用默认配置就好了。
下位机配置
那么Sci0到底是个什么东西呢? 通过翻阅手册和学习示例代码发现:其实就是全芯片仿真中的SCI0。
全芯片仿真 提供了对SCI模块的模拟。并提供了非映射寄存器SCIInput/SCIInputH 和SerialInput来发送字符到SCI模块,非映射寄存器SCIOutput/SCIOutputH 和SerialOutput 来保存SCI模块发来的字符。
以下是其模拟的SCI寄存器
表 2.模拟的SCI寄存器
表 3. 没有映射到内存的SCI寄存器
寄存器 | 描述 |
---|---|
SCIInput | 发送一个字符到SCI。从SCI接收到的值可以通过读取SCDR来获得。第9位是从SCIInputH寄存器获得的。读SCIInput没有任何意义。 bit 7-0 发送到SCI。 |
SCIInputH | 发送一个字符到SCI,包含与SCIInput相关的第9个bit。必须在写SCIInput寄存器之前写它。读SCIInputH 没有任何意义。 bit 0(第9bit)发送到SCI。 |
SCIOutput | 接收一个来自SCI的字符。对SCDR的写访问会使SCIOutput收到值。第9位会写入SCIInputH寄存器。写SCIOutput没有任何意义。 SCI发送来的bit 7-0。 |
SCIOutputH | 接收一个来自SCI的字符。包含与SCIOutput 相关的第9个bit。写SCIOutputH没有任何意义。 SCI发送来的bit 9。 |
SerialInput | SCIInput寄存器的别名。SerialInput将SCI连接到terminal。不支持第9位。读SerialInput 没有任何意义。 从terminal窗口发送到SCI的数据的第7-0 bit。 |
SerialOutput | SCIOutput寄存器的别名。SCIOutput将SCI连接到terminal。不支持第9位。写SCIOutput没有任何意义。 从SCI发送到terminal窗口的数据的第7-0 bit。 |
.
这样就知道图3中virtual SCI组合框中的Sci0.SerialOutput和Sci0.SerialInput是什么了吧。
但这是从HIWAVE的角度来看的。我们在下位机编程的时候要怎么做呢?
手册上也没有说的很清楚,还好,CodeWarrior给了示例的代码,可以在
安装目录\ (CodeWarrior_Examples)\HCS12X\HCS12X_C_Calc
或者
安装目录\ (CodeWarrior_Examples)\HC12\HC12 SIMULATOR\HC12 C_Calc
里找到。
观察示例代码发现,CodeWarrior提供了terminal.h、termio.h、inout.h等来提供各种等级的通信操作。
在termio12.c中观测到,虽然它定义了一个数据结构:
typedef struct {
unsigned char SCxBDH;
unsigned char SCxBDL;
unsigned char SCxCR1;
unsigned char SCxCR2;
unsigned char SCxSR1;
unsigned char SCxSR2;
unsigned char SCxDRH;
unsigned char SCxDRL;
} SCIStruct;
/* terminal.wnd */
#define SCI_ADDR 0x00c8
#define SCI (*((SCIStruct*)(SCI_ADDR)))
还通过指针的方式来访问特定的地址,看着很高端,实际上这地址就是SCI0的那几个寄存器,其实最底层的通信就和直接操作SCI0没啥区别(当然,他还提供了读取整数等一些对数据流的封装)。
那还剩一个问题,示例代码是使用同步查询标志位的方式来发送接收的,那能不能使用中断呢?
亲测可以使用。使用我自己封装的(使用中断的)SCI模块http://blog.csdn.net/lin_strong/article/details/73521774,能够在SCI0上和terminal正常通信。
所以绕了这么大一圈,其实结论就是
总结
如果你想在全芯片仿真中和terminal控件通信,那就直接正常使用SCI0就行。SCI0发出的字符会显示在终端上,而你在terminal界面上输入的字符会被发送到SCI0。
对,就是这么简单。。
参考文献
[1] Freescale semiconductor. S12(X) Debugger Manual . 2010.