kaiyun官方注册
您所在的位置: 首页> 嵌入式技术> 业界动态> 如何在SDL中调用C语言函数

如何在SDL中调用C语言函数

2008-10-09
作者:段红光 罗一静

摘 要:从实际工作出发,提出了在SDL中调用C语言函数的必要性,并给出了SDL语言中使用C语言数据类型、公共变量以及调用C语言函数的方法。这种方法具有很强的实用性,大大提高了工作效率,加快了实时多任务系统" title="多任务系统">多任务系统应用软件的开发。此方法实际应用于第三代移动通信系统TD-SCDMA" title="TD-SCDMA">TD-SCDMA高层信令" title="信令">信令的开发,收到了良好效果。

关键词:进程 SDL 实时多任务系统 TD-SCDMA C语言函数 数据类型 公共变量

  SDL(Specification and Description Language)是CCITT推荐的规范描述语言。经过ITU-T的发展和标准化,定义在蓝皮书Z.100建议中。1988年推出第一个正式版,以后每四年进行一次增补更新。作为国际标准化的正式语言,用来规范描述实时系统。目前SDL-2000是SDL最新版本。作为SDL相关技术Z.120建议——消息序列图MSC(Message Sequence Charts)和Z.105建议——抽象语法符号ASN.1(Abstract Syntax Notation One)和SDL一起形成一个完整的描述语言。本文中介绍的SDL软件由Telelogic Tau AB公司提供。

  在协议软件的开发流程中,SDL应用在系统规范描述和设计阶段。它完全独立于硬件实现和操作系统。Telelogic Tau公司提供的SDL软件不仅可以用于规范描述和设计,它还可以把SDL的描述和设计直接生成标准的C代码;用户也可以直接在SDL描述和设计中嵌入C代码,从而完成部分功能。经SDL描述产生的C代码(包括嵌入的C代码)可以直接与多种嵌入式(或非嵌入式)实时多任务操作系统(RTOS)集成,如NUCLUES、pSOS、Solaris、Vrtx、OSE等。集成后的代码可以直接在目标板上运行,从而方便用户进行协议软件的开发。

  虽然SDL软件具有很强的开发功能,但是在重庆邮电学院信科公司的TD-SCDMA系统高层信令的二三层开发中,也遇到了许多问题,主要有:

  (1)由于TD-SCDMA系统的高层信令是由几个部门共同负责的,除了二三层以外还有MMI和物理层控制部分的软件,不可能将各个部门统一使用SDL软件共同完成系统的信令开发工作。每个部门最终提供的应该是标准的C语言源代码" title="源代码">源代码,最后在实时操作系统上集成。利用SDL软件生成的C源代码,不便于和其它部分的代码相互集成。

  (2)高层二三层信令是一个很复杂的系统,各个进程之间需要大量的数据交换,而SDL要求所有进程间的数据交流必须通过信号来完成(虽然可以使用SDL的VIEW功能,但使用不方便)。在系统启动后,很多数据需要进行通信,系统资源将被白白浪费在通信上面。

  但是SDL的测试功能特别强大,可以从不同角度对SDL描述进行测试,发现错误及时返回进行修改。如果没有SDL的TTCN测试,所有设计结果在硬件平台上测试将困难重重,即使可以对硬件平台运行结果进行跟踪,也始终没有TTCN测试结果MSC图方便。并且SDL可以对系统任何部分独立测试。在SDL设计结果和RTOS系统集成之前,基本保证了SDL设计阶段的正确性,减少了繁琐的板级代码调试,从而可在较短时间内将SDL设计结果移植到硬件工作平台,提高了工作效率。

  为了SDL软件的设计结果既可以被SDL软件的TTCN测试又可以直接和其它C语言源代码集成,必须解决一个问题——如何在SDL中调用C语言函数。

1 实现模式

  SDL内核对SDL进程的管理采用了消息驱动事件的方法,SDL内核对SDL进程的调度是根据消息队列中的消息来进行的。如图1,表明了SDL进程、SDL内核和SDL信号队列的关系。

  SDL图形描述转换成C源代码,没有系统(system)和功能块(block)的概念,只有进程和通信,它们由SDL内核程序管理和协调。在各个进程间没有全局变量,所有的数据交换都要通过信号来传递。一个进程要发送信号到另外一个进程,需要先发送到SDL信号队列中等待SDL内核程序的处理。

  在实时多任务系统的编程中,最关心的是状态的划分和在什么状态下收到什么信号以及做何种处理。所以在SDL中,应该利用标准C语言源代码对数据、信号定义并对收到的信号进行处理。要求这部分代码既能在SDL中进行测试又可以在实时操作系统中使用。

  在整个开发过程中,始终坚持这样一个原则,利用SDL来划分通信模块,在协议中规定的原语尽量用信号来传递,而非标准的信息则使用公共变量,进程的代码利用C语言来实现;最后利用TTCN进行全面的" title="面的">面的测试。在TD-SCDMA信令设计中证实这种设想可行。图2就是TD-SCDMA系统部分高层软件的开发模式图。

  在开发的初始阶段,根据TD-SCDMA系统协议TSM,考虑将系统划分成多少个进程,各进程间需要哪些信号及全局变量数据,然后定义数据类型、编写C语言源代码。所有C源代码是按照在什么状态下接收什么信号,处理以后发送什么信号格式来完成。这样编写的代码既可以在RTOS中应用,又可以满足SDL的要求,方便TTCN的测试。如图2利用标准C完成的源代码可以和SDL相互集成,并且进行TTCN测试;同时又可以和RTOS系统集成,在实际硬件环境中运行。

  完成的C语言源代码,经过TTCN测试后,保证了信号处理的正确性。在软件开发后期,只需根据协议变换作适当的程序修改和C语言源代码的移植即可。

  在SDL的说明文档中,提到了怎样将C语言函数应用于SDL系统;但是这种方法经过多次实验效果均不理想,即使能够实现也是受到诸多限制。所以舍弃了SDL提供的方法,最终找到了一种切实可行的方法,方法如3小节描述。

2 实现过程

  C源代码不能直接在SDL中使用。首先应该利用sdth2sdl.exe软件将C语言的头文件转换成SDL的文本描述(PR描述),如图3。然后在SDL的Organizer界面中,将文本描述转换成图形描述方式,它以SDL的SUN文件形式存在。最后在设计的SDL系统中利用use关键字声明即可。具体如下:

  (1)利用sdth2sdl.exe程序转换C语言头文件。sdth2sdl.exe是Telelogic Tau AB公司提供的可执行文件。在使用该文件时,需要操作系统装有MSC7.00 或是MSVC++编译器(不能是Borland C编译器)。sdth2sdl.exe自动调用标准C的编译器,进行C语法检查,再将C部分代码转化成SDL的PR格式。sdth2sdl.exe只检查头文件的数据类型、数据定义以及函数的声明。在该过程中,不检查具体C语言函数的语法。实际上,C语言函数不能直接转换成SDL的图形描述或文本描述方式。

  为了方便使用sdth2sdl工具,sdth2sdl是一个可以带参数的DOS程序,格式为:

  sdth2sdl [参数选项] 要转换的C语言头文件

  它的参数选项如表1。在实际应用中,最常用的参数选项有n、s、I三个参数选项。

  (2)将SDL的PR文件转换成GR方式。利用SDTH2SDL

  程序生成一个以PR为扩展名的SDL Package文件。在SDL的Organizer界面的Generate菜单中有“Convert to GR ...”选项,利用SDL的Convert to GR对话框完成PR文件到GR格式的转换。生成的SDL Package文件的名字是SDL PR描述内部指定的名字。

  (3)在SDL系统中声明。在SDL进程中,不能直接使用C语言的数据类型、变量定义和函数,上面生成的是SDL Package文件,需要在system中利用SDL关键字use加以声明。格式为use package文件名。

  这样可以在SDL进程中任意使用C语言头文件的函数、数据类型及变量。虽然这些定义在SDL中都可以使用,但是它们还必须遵守SDL调用C变量和函数的规则。

  ①变量调用

  由于SDL可以调用C语言函数,基本上系统所有的处理由C语言函数来完成。所以在SDL和C源代码所用的公共变量很少,仅仅只有一些SDL专用的数据,例如控制SDL的分支等。调用格式为:

  变量赋值: Call Set_变量名

  去变量值: Call Get_变量名

  ②数据类型引用

  虽然整个系统的任务在C源代码中完成,但是在进行信号处理时,SDL需要保存信号到变量中(SDL描述要求),信号类型在C语言中定义。C语言数据类型转换成SDL数据类型时,保持了原来的数据类型名字,在SDL中只要按照SDL规则定义数据即可。

  ③函数调用

  C语言函数的调用和变量调用、数据类型引用基本相同,需要注意的是函数的参数。

调用格式: Call 函数名字(函数需要的实参)

  由于C语言编写的C函数中可以使用全局变量,大大方便了C语言在SDL中的应用,需要处理的公共数据可以不以SDL信号方式进行传递。例如在TD-SCDMA高层信令的设计中,小区信息以及系统消息是很多进程都需要使用的,就可以作为全局变量使用。

3 举例说明

  下面的例子是在空闲状态下收到来自物理层的测量报告IdleNcellMeasInd信号和发送到物理层进行小区BSIC解读的BsicDecodeReq请求信号。将分以下几个步骤来说明:

  (1) C语言头文件trr.h的编写

所有在SDL中调用到的数据类型、全局变量和函数必须在C语言头文件中声明,只有声明过的才能在SDL中调用或引用。在头文件中可以使用任何标准C语法。在下面的头文件中,由于篇幅关系,没有给出详细的下级数据类型的定义。

  #ifndef __TRR__

  #define __TRR__

  typedef struct MessageHeader

  }

int header;          /*实时操作系统的数据头,不同的RTOS的T_MsgHeaher定义不相同*/

  { T_MessageHeader;

  typedef struct t_IdleNcellMeasIndTag

  }

int numMeas; /*邻近小区数*/

NcellList ncellList;   /*邻近小区标识表*/

int rscpLevelList[MAX_NCELL]; /*邻近小区功率测量结果*/

  { T_IdleNcellMeasInd;

  typedef struct h_t_IdleNcellMeasInd

  }

T_MessageHeader signalHeader;    /*实时多任务系统头标识*/

T_IdleNcellMeasInd IdleNcellMeasInd; /*邻近小区测量数据*/

  { H_T_IdleNcellMeasInd;

  typedef struct t_BsicDecodeReqTag

  }

NcellNccDecode ncc;        /*邻近小区BSIC数据*/

  {T_BsicDecodeReq;

  typedef struct h_t_BsicDecodeReq

  }

T_MsgHeader signalHeader;

T_BsicDecodeReq BsicDecodeReq;

  { H_T_BsicDecodeReq;

  extern H_T_IdleNcellMeasInd s_trr_IdleNcellMeasInd;

/*接收处理的变量*/

  extern H_T_BsicDecodeReq s_trr_BsicDecodeReq;

/*需要发送的变量*/

  int trr03_01IdleNcellMeasInd(H_T_IdleNcellMeasInd *p);

/*收到测量的处理程序*/

  /*#include ″trr.c″*/

  #endif

  在trr.h中,使用sdth2sdl时应该将#include “trr.c”屏蔽,不需要将trr.c文件编译和转换成SDL的文本描述。但在生成SDL的TTCN或Simulator、Validator的可执行文件时,需要将C语言屏蔽符/* */去掉。这样在生成可执行文件时,SDL将trr.c定义的内容和SDL描述直接汇合编译连接在一起。

  (2) C语言函数trr.c的编写

  在C语言头文件中声明的全局变量和函数实体都是在C源代码中定义的。在trr.c文件中定义s_trr_IdleNcellMeasInd、s_trr_BsicDecodeReq全局变量和int trr03_01IdleNcellMeasInd()函数。C语言函数不直接转换成SDL描述,可以支持标准C语言的所有使用方法。

  #include “trr.h”

  H_T_IdleNcellMeasInd s_trr_IdleNcellMeasInd;

/*定义接收信号的变量*/

  H_T_BsicDecodeReq s_trr_BsicDecodeReq;

/*定义发送信号的变量*/

  int trr03_01IdleNcellMeasInd(H_T_IdleNcellMeasInd *p)

  }

  int tempCount;

  int rscp[MAX_NCELL];

 s_trr_BsicDecodeReq.signalHeader= p->signalHeader;

 rscp[tempCount] = p-> IdleNcellMeasInd. RscpLev-

elList[tempCount]; /*保存测量*/

 s_trr_BsicDecodeReq.BsicDecodeReq.ncc.numMeas=10;

  for(tempCount=0;tempCount

  }

s_trr_BsicDecodeReq.BsicDecodeReq.ncc.frequency

NUM_NCELLS]=tempCount;

s_trr_BsicDecodeReq. BsicDecodeReq.ncc.syncCode

  [NUM_NCELLS]=tempCount;

s_trr_BsicDecodeReq. BsicDecodeReq.ncc.syncDiff

[NUM_NCELLS]=tempCount;

  {

  return TRR_IDL; /* # define TRR_IDL 1*/

  { /*函数的返回值表明是否需要发送BsicDecodeReq信号*/

  在该例子中,函数返回值决定了是否需要发送BsicDecodeReq信号到物理层。利用这种方法可以确定SDL描述的分支处理。

  (3) sdth2sdl的使用

  编写完成trr.h文件后,就可以将trr.h文件转换成SDL的文本描述,在DOS系统提示符下执行下列命令:

  sdth2sdl -n trr -s c:td_scdmaprtsm_trr.pr -o ″-Ic:bc5include -Ic:tdscdmatrrinclude″ trr.h

  在编译过程中,如果C语言源代码编写不正确,将有错误提示。必须根据提示修正所有的错误(每个头文件的最后一行必须是空行),直到生成正确的tsm_rr.pr文件。在tsm_rr.pr文件中指明了SDL package的名字为trr。最后利用SDL Organizer的PR转换到GR工具,生成trr.sun文件。

  (4) SDL进程的调用

  C语言在SDL中应用最终在进程中实现。根据SDL的要求,接收信号必须先保存到一个变量中,例如收到IdleNcellMeasInd信号必须先保存在tempReceiveSignal变量中;然后调用trr03_01IdleNcellMeasInd()来处理该信号,并在该处理过程中产生BsicDecodeReq信号的内容s_trr_BsicDecodeReq,由SDL发送出去。如图4。

  在实时多任务系统中,为了提高系统的工作效率,常常用传递指针的方式传递信号,所以在上例中int trr03_01IdleNcellMeasInd()的形参是一个C语言指针的形式。在C语言转换成SDL时,虽然可以将数据类型转换成SDL的数据类型格式,但是在SDL中不便直接定义指针,所以将接收的信号定义成一个与函数形参相同的数据类型变量,利用SDL的“&”取地址符号,将变量转换成指针使用。在该例中,Call trr03_01IdleNcellMeasInd(&tempReceiveSignal)。其它请参考图4。

  并不是所有的设计代码都可以由C语言来完成,SDL信号的发送和接收机制、时钟处理只能由SDL自己处理。其实这部分对不同的RTOS系统是不相同的,所以必须利用C语言的预编译开关将它们分开,对不同系统作不同的编写。

  这种利用SDL调用C语言函数进行通信软件的开发是根据实际工作需要提出的,虽然不能保证是最好的方法,但是经过长期的研究和探索,在实际中的应用充分表明了这种方法是切实可行的。TD-SCDMA系统的高层信令二三层就是利用这种方法完成的。

参考文献

1 Telelogic tau AB.Telelogic tauTM SDL suite 4.0 Getting Started. 2001

2 Telelogic tau AB.Telelogic tauTM SDL suite 4.0 Methodology Guidelines.2001

3 CWTS.TSM 04.08 Mobile radio interface layer 3 specification. V2.2.0.2002

4 Nucleus company.Nucleus PLUS internals.Accelerated Technology.2000, 0001027-001 Rev 101

5 Nucleus company.Nucleus PLUS Reference Manual. 2000, 0001026-001 Rev.102

6 Nucleus company.ARM Developer Suite Nucleus Target Specific Notes.2000, 0001000-001 Rev.108

本站内容除特别声明的原创文章之外,转载内容只为传递更多信息,并不代表本网站赞同其观点。转载的所有的文章、图片、音/视频文件等资料的版权归版权所有权人所有。本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如涉及作品内容、版权和其它问题,请及时通过电子邮件或电话通知我们,以便迅速采取适当措施,避免给双方造成不必要的经济损失。联系电话:010-82306116;邮箱:aet@chinaaet.com。
Baidu
map