ccs中dsp、bios工具的使用_第1页
ccs中dsp、bios工具的使用_第2页
ccs中dsp、bios工具的使用_第3页
ccs中dsp、bios工具的使用_第4页
ccs中dsp、bios工具的使用_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

.z.评语**成绩评语"DSP技术"课程论文题目CCS中DSP/BIOS工具的使用作者班级_院别专业_完成时间目录一、DSP/BIOS简介……………………1二、DSP/BIOS的组件构成……………1三、DSP/BIOS的启动顺序……………2四、DSP/BIOS的配置…………………2五、根底类的DSP/BIOSAPI调用……………………15六、DSP\BIOS的中断、优先级………22七、参考文献…………23-.z.摘要:DSP/BIOS的静态配置是利用CCS提供的配置工具完成,包括图形化配置工具和文本配置工具。图形化工具层次清晰,比拟直观,而文本工具更加灵活。一、DSP/BIOS简介DSP/BIOS是CCS中集成的一个简易的嵌入式实时操作系统,能够大大方便用户编写多任务应用程序。DSP/BIOS拥有很多实时嵌入式操作系统的功能,如任务的调度,任务间的同步和通信,内存管理,实时时钟管理,中断效劳管理等。有了它,用户可以编写复杂的多线程程序,并且会占用更少的CPU和内存资源。DSP/BIOS是一个可用于实时调度、同步,主机和目标机通信,以及实时分析系统上的一个可裁减实时内核,它提供了抢占式的多任务调度,对硬件的及时反响,实时分析和配置工具等。同时提供标准的API接口,易于使用。它是TI的e*pressDSP实时软件技术的的一个关键局部。二、DSP/BIOS的组件构成DSP/BIOS在一个主机/目标机环境中的组件分布如下所示:DSP/BIOSAPI:编写的程序可以调用API接口函数;DSP/BIOS配置:创立的配置文件定义了程序使用的静态BIOS对象;DSP/BIOS分析工具:集成在CCS上的一些BIOS分析工具可以对运行与目标设备上的程序进展监测,包括CPU负载、时间、日志、线程执行状态等。DSP/BIOS分为很多模块,提供的所有API函数都按照模块分类,以模块名加下划线开头来命名,如图

40所示为DSP/BIOS的全部模块。图40三、DSP/BIOS的启动顺序当DSP/BIOS的应用程序启动时,一般遵循下面的步骤:〔一〕初始化DSP:DSP/BIOS程序从C/C++环境入口c_int00开场运行。对于C6000平台,在c_int00开场处,系统栈指针〔B15〕和全局页指针〔B14〕被分别设置在堆栈断的末尾和.bss断的开场。控制存放器AMR、IER、CSR等被初始化;〔二〕初始化.bss段:当堆栈被设置完成后,初始化任务被调用,利用.cinit的记录对.bss断的变量进展初始化;〔三〕调用BIOS_init初始化用到的各个模块:BIOS_init调用MOD_init对配置用到的各个模块进展初始化,包括HWI_init、HST_init、IDL_init等;〔四〕处理.pinit表:.pinit表包含一些指向初始化函数的指针,对C++程序,全局对象类的创立也在此时完成;〔五〕调用用户程序的main函数:用户main函数可以是C/C++函数或者汇编语言函数,对于汇编函数,使用_main的函数名。由于此时的硬件、软件中断还没有被使能,所以在用户主函数的初始化中需要注意,可以使能单独的中断屏蔽位,但是不能调用类似HWI_enable的接口来使能全局中断;〔六〕调用BIOS_start启动DSP/BIOS:BIOS_start在用户main函数退出后被调用,它负责使能使用的各个模块并调用MOD_startup启动每个模块。包括CLK_startup、PIP_startup、SWI_startup、HWI_startup等。当TSK管理模块在配置中被使用时,TSK_startup被执行,并且BIOS_start将不会完毕返回;〔七〕执行idle循环:有两种方式进入idle循环。当TSK管理模块使能时,任务调度器运行的TSK_idle任务调用IDL_loop在其它任务空闲时进入idle循环;当TSK模块未被使用时,BIOS_start调用将返回,并执行IDL_loop进入永久的idle循环,此时硬件和软件中断可以抢占idle循环得到执行。由于idle循环中管理和主机的通信,因此主机和目标机之间的数据交互可以进展了。四、DSP/BIOS的配置DSP/BIOS的静态配置是利用CCS提供的配置工具完成,包括图形化配置工具和文本配置工具。图形化工具层次清晰,比拟直观,而文本工具更加灵活。通常使用图形化的配置方法,下面对主要的模块配置做一些介绍。〔一〕GlobalSettingProperties右键点击"GlobalSettings〞,点击"What’sThis〞,会弹出帮助窗口,该文件中有GlobalSettingProperties的各项设置说明。下面介绍的其他如MEM、LOG等配置都可以用同样的方法得到相应的帮助。选择弹出菜单中的"Properties〞,如图

41所示。图41弹出如图

42所示对话框:图42一般选择默认设置即可,CLKOUT项需要根据DSP硬件单板提供的工作时钟设置,Himalaya通常运行在1GHz频率。DSPEndianMode项根据实际情况设置。〔二〕MEM设置MEM模块设置中可以根据具体情况设置不同的内存段,其中存在一个默认的IRAM片内内存段。需要注意的是,首先必须在IRAM段上设置一个heap段落,用于BIOS的内部使用。设置方法是在IRAM段上右键选择"Properties〞,弹出如图

43对话框,必须设置红线框中的选项,heapsize可根据情况具体设置。图43接下来配置MEM全局属性,右键点击配置窗口中的"MEM…〞,如图

44所示:图44点击"Properties〞,弹出如图

45所示窗口:图45如图红线框中,两个heap段都要选择为IRAM,"StackSize〞项需要根据实际情况设置最大的栈大小,其他使用缺省设置即可。在图

44的菜单中,点击"InsertMEM〞可创立新的内存段。在新的内存段名上右键选择"Properties〞弹出如图

43窗口,根据情况设置base〔基地址〕、len〔段长度〕、heapsize〔用于MEM动态内存分配的堆大小〕。〔三〕LOG设置LOG用于输出和记录一些打印信息,默认存在一个LOG_system对象,是系统内部用来处理打印信息的,不需要去设置。可以增加新的LOG对象,用来在应用程序中输出打印信息。如图

46,在LOG标签上右键选择"InsertLOG〞,填写对象名LOG_test即建立了一个新的LOG对象。图46在LOG_test标签上右键选择"Properties〞,弹出如图

47窗口,可对此LOG对象属性作一些设置。具体设置含义可通过Help查看。图47〔四〕

CLK设置在CLK属性中通常选择定时器Timer0作为DSP/BIOS的基准时钟,计时分辩率设置为每秒1000次中断,在1GHz系统时钟下,近似为每次定时中断间隔999.996微秒。TimerMode选择为32bitunchained模式,即使用TCI6482的TMR0的TIMLO作为Timer0,而TIMHI还可以作其它用途使用。CLK属性配置界面如图

48所示:图48〔五〕HWI设置HWI〔硬中断〕中包含HWI_INT4到HWI_INT15可用来定义用户自己的硬件中断,HWI_RESET、HWI_NMI和HWI_RESERVED不要去改动。如图

49,每个硬HWI的优先级从上到下逐渐降低。图49选择HWI_INT10为例,来设置EMAC/MDIO的中断,需要填写中断事件号17,并且填写中断效劳程序名〔C函数前面需要加下划线〕如图50所示:图50在Dispatcher页面,选择"UseDispatcher〞由BIOS代理控制中断确实认和去除,不需要用户中断效劳程序干预,比拟简便。如图51:图51〔六〕SWI设置SWI〔软中断〕的优先级在HWI之后,但是比TSK高,可以通过右键菜单中的"InsertSWI〞创立一个SWI对象,可以指定SWI内部优先级,从0(最低)到14(最高)。如图

52:图52〔七〕TSK设置在TSKManager〔任务管理器〕中可以根据需要创立各种任务,任务间是根据优先级抢占策略来进展调度的,TSK提供有多种优先级别,包括-1(Suspend)、0(Idle)、1(最低)到15(最高)。如图

53:图53在TSKManager上右键选择"InsertTSK〞并填写任务名称后就可以创立一个任务,在相应任务上右键选择"Properties〞可对任务属性进展设置,如图

54:图54StackSize〔最大堆栈大小〕和Priority〔优先级〕需要根据任务的具体情况进展设置。在页面,填写任务实体函数名〔C函数前面加一个下划线〕,如图

55:图55〔八〕Synchronization设置DSP/BIOS中任务间的通信和同步可由SEM、MB*、QUE、LCK四个模块完成:SEM〔信号量〕:用于任务同步和互斥,有计数功能,根据需要使用;MB*〔〕:也用于任务同步,可以传递少量数据,根据需要使用;QUE〔队列〕:可实现任务同步和资源的共享,根据需要使用;LCK〔资源锁〕:实现对共享资源的互斥,根据需要使用。四种同步模块对象都可以通过各自的右键菜单中"Insert…〞来创立,并可对其属性作相应的设置。如图

56所示:图56〔九〕Input/Output设置这里可以设置一些输入/输出相关的高级设置,具体可通过CCS的帮助项来了解。一般不需要进展设置。只有RTD*〔实时数据交换〕,需要根据目标环境的情况对数据交换模式进展一下选择,用来在调试中主机和目标机进展数据交换。可以是仿真器环境的JTAG模式,或者是模拟器环境的Simulator模式。如图

57所示:五、根底类的DSP/BIOSAPI调用〔一〕时钟管理CLK

1.Unsncounts

=CLK_countspms(void)

返回每毫秒的定时器高分辨率时钟的计数值

2.LgUnscurrtime=CLK_gethtime(void)

返回高分辨率时钟的计数值超过32bit归零

高分辨率时钟是DSP时钟除以(TDDR+1)

3.LgUnscurrtime=CLK_getltime(void)

返回低分辨率时钟的计数值超过32bit归零

高分辨率时钟是DSP时钟除以(TDDR+1)再除以(PRD+1)

4.Unsperiod

=CLK_getprd(void)

返回CLK管理器周期存放器的值

(二)周期函数PRD

1.LgUnsnum

=PRD_getticks(void)

返回32位周期函数管理计数值

2.voidPRD_start(PRD_Obj*period)

启动PRD模块计数器,一般地,mode=one-shot

3.voidPRD_stop(PRD_Obj*period)

关闭PRD模块计数器

4.voidPRD_tick(void)

对周期模块的计数器加1,以便周期模块管理器确定哪个周期性函数得以运行

(三)软件中断管理SWI

1.voidSWI_andn(SWI_Obj*swi,Unsmask)

mask屏蔽字参数

将值与mask做与运算,并用结果代替以前的值,假设为0,启动软件中断,恢复初始值

2.voidSWI_andn(SWI_Obj*swi)

将值减1,并用结果代替以前的值,假设为0,启动软件中断,恢复初始值

3.voidSWI_disable(Void)

制止软件中断

4.voidSWI_enable(Void)

使能软件中断

5.Unsnum=SWI_getmbo*(void)

返回当前SWI对象在被执行的值,假设中断已经开场执行,DSP/BIOS会先保存此值

6.Unskey=SWI_getpri(SWI_Obj*swi)

返回指定的SWI对象的优先级

7.voidSWI_inc(SWI_Obj*swi)

将指定的SWI对象的值加1,同时启动软件中断,就算用户调用屡次,最终执行一次。

8.voidSWI_or(SWI_Obj*swi,Unsmask)

mask屏蔽字参数

将启动指定的软件中断,并将此软件中断的值与mask做与运算,并用结果代替以前的值,等到中断完成之后,值恢复为初始值,一般地,调用SWI_getmbo*获得触发此软件中断的值

9.voidSWI_post(SWI_Handleswi)

启动指定的SWI对象的软件中断,此函数不受值的影响,也不影响值。一般地,周期性低启动一个软件中断,将_SWI_post填入PRD对象的函数设置栏,启动软件中断的参数写入arg0

10.Unskey=SWI_raisepri(Unsmask)

提高SWI软件中断的优先级,一般地

key=SWI_raisepri(SWI_getpri(&swi_1));

--accesssharedresouces--

SWI_restorepri(key)

11.voidSWI_restorepri(Unskey)

恢复原来的优先级

12.SWI_Obj*swi=SWI_self(void)

当前执行的SWI对象的软件中断的地址

(四)信息输出管理LOG

1.voidLOG_disable(LOG_Obj*log)

关闭指定对向的日志功能

2.voidLOG_enable(LOG_Obj*log)

开启指定对向的日志功能

3.voidLOG_error(Stringformat,Argarg0)

voidLOG_message(Stringformat,Argarg0)

前一个函数可以将一个事件、数据或出错信息按照指定的格式串写入系统日志,不受TRC跟踪管理模块的影响,后一个函数类似于前一个函数,但是受到TRC跟踪管理模块的影响

4.voidLOG_event(LOG_Obj*log,Argarg0,Argarg1,Argarg2)

将未格式化的事件消息写入日志中

5.voidLOG_printf(LOG_Obj*log,Stringformat,intarg0,intarg1)

指定的LOG窗口显示消息%d%*%o%s

6.voidLOG_reset(LOG_Obj*log)

复位日志缓冲区

(五)存储器管理MEM

1.void*addr=MEM_alloc(intsegid,Unssize,Unsalign)

指定存储段分配连续块,返回起始地址

segid=存储段的标识符或者ID号

size块大小等于多少个字

align边界条件只为0或2的幂假设align为0、1则无约束

2.void*addr=MEM_calloc(segid,size,align)

分配内存并初始化为0

3.intsegid=MEM_define(Ptrbase,Unslength,MEM_Attrs*attrs)

定义一个新的存储段。返回值为存储段的ID标号,attr参数为NULL,会按照默认参数进展配置,段的参数由构造体typeMEM_Attrs规定,此函数仅在main函数中使用

base:新段的基地址

length:段长度

attrs:段属性

4.boolstatus=MEM_free(segid,addr,size)

释放申请的动态内存不能在SWI和HWI中调用,调用之前,用LCK中API查看内存块的锁定情况

5.voidMEM_redefine(segid,base,length)

重新定义一个存储段,只能在main中调用

6.boolstatus=MEM_stat(intsegid,MEM_Stat*statbuf)

segid存储段标识符

statbuf状态缓存区指针

structmem_stat{

Unssize;//存储段大小

Unsused;//已经使用的数量

Unslength;//最**续存储块长度

同理:假设segid有效,则MEM_stat返回TRUE

不能在SWI和HWI中使用,应判断锁定情况

7.void*addr=MEM_valloc(intsegid,Unssize,Unsalign,charvalue)

先申请内存,初始化为指定的值value(六)C6000专用模块C64*

1.Unsoldmask=C64_diableIER(Unsmask)

关闭相应的中断返回值实际屏蔽的中断

2.voidC64_enableIER(Unsoldmask)

开放相应的中断

Unsoldmask;

oldmask=C64_disableIER(0*1);//disableINT0

C64_enableIER(oldmask);

//enableINT0

3.voidC64_plug(intvecid,F*nf*n,intdmachan)

插入一个中断向量

intvecid:中断序号

F*nf*n:中断效劳程序的函数指针

intdmachan:插入操作使用的DMA通道

将ISFP写到中断效劳表IST中。假设IST在外部RAM,则CPU复制代替DMA,此时DMA为-1

IST在片内RAM时,使用DMA方式,是0,1,2,3用户保证在函数调用时该DMA通道有效

(七)统计模块STS

1.voidSTS_add(STS_Obj*sts,LgIntvalue)

使用我们提供的数据更新STS统计对象的Total,Count,Ma*等参数

传入一个32位参数,Count加1,Total累加传递的32位参数,MA*记录传递参数的最大值

2.voidSTS_delta(STA_Obj*sts,LgIntvalue)

每个对象都包含有初始值,该初始值由配置文件指定或者由STS_set函数设置

STS_delta先计算当前传递参数与先前初始值只差,然后调用STS_add更新统计累加值

一般和STS_set一起用

eg:

STS_set〔&sts,CLK_gethtime());

STS_delta(&sts,CLK_gethtime());

3.voidSTS_reset(STS_Obj*sts)

复位统计对象中的累加值。Count和Total设置为0.MA*成为最大的负值。

4.voidSTS_set(STS_Obj*sts,LgIntvalue)

监视或统计程序的执行时间(八)统计类模块TRC

1.TRC_LOGCLK日志记录定时器中断

2.TRC_LOGPRD日志记录周期时隙和周期函数的开场

3.TRC_LOGSWI日志记录软件中断的启动和完成

4.TRC_LOGTSK日志记录任务处于准备好、开场、停顿、继续执行、终止等事件

5.TRC_STSHWI收集关于HWI统计数据

6.TRC_STSPIP写管道和读管道帧进展计数

7.TRC_STSPRD执行期间CLK时隙个数的统计数据

8.TRC_STSSWISWI执行时间的统计数据

9.TRC_STSTSKTSK执行时间的统计数据从TSK准备好到调用TSKdeltatime都要收集

10.TRC_USER0ANDTRC_USER1和TRC_query一起用执行和忽略结果的设备调用

11.TRC_GBLHOST执行所有的隐藏仪器功能,此比特位能够开场或停顿收集所有开启的跟踪类型

12.TRC_GBLTARG执行所有的隐藏仪器功能,此比特位只能被目标程序设置(九)任务管理TSK任务管理模块

1.voidTSK_checkstacks(TSK_Handleoldtask,TSK_Handlenewtask)

无论是新任务还是老任务,如果堆栈的最后位置上都没有RG_STACKSTAMP标识,则TSK_checkstacks就会

报错SYS_abort,出现这种情况可能是由于上一个任务堆栈溢出或无效的存储占用了新任务的堆栈

一般地,用TSK_checkstacks(TSK_self(),TSK_self())来检查堆栈

定义Switch函数,这样在任务切换时自动调用堆栈检查函数:

voidmyswitchf*n(TSK_Handleoldtask,TSK_Handlenewtask)

{

...

TSK_checkstacks(oldtask,newtask);

...

}

2.TSK_Handletask=TSK_create(F*nf*n,TSK_Attrs*attr,Arg[arg,]...)

创立一个调用函数f*n的任务对象,返回新对象的句柄,失败返回NULL。

调用此函数是动态创立,而在配置工具中创立是静态创立,二者效果一样。

静态创立的任务对象,创立函数将在BIOS_start函数中自动调用。BIOS_start函数在main函数之后,

在后台IDL循环之前运行。而动态创立的任务处于Ready状态。函数参数最多不超过8个。

任务对象函数f*n返回时,自动调用TSK_e*it函数。

解析:TSK_Attrs*attrs任务参数指针

structTSK_Attrs{

intpriority;

Ptrstack;

Unsstacksize;

#ifdef_64_//imitateC55series.tocheck

Unssysstacksize;

#endif

Unsstackseg;

Ptrenviron;

Stringname;

boole*itflag;

}

3.voidTSK_delete(TSK_Handletask)

从所有内部队列里面删除这个任务,并且调用MEM_free释放任务对象和堆栈。

只能删除处于完毕状态的任务,也可调用删除的钩子函数。

voidmyDeleteF*n(TSK_Handletask);

4.voidTSK_deltatime(TSK_Handletask)

累计从任务准备好到执行此函数时候的时间差

如果未调用此函数,则就算翻开任务统计累加器选项,统计对象也不会更新

一般地,统计时先用TSK_settime函数记录起始点,此函数记录终点。

5.voidTSK_settime(TSK_Handletask)

设定统计初始值

voidtask()

{

--dosomestartupwork--

TSK_settime(TSK_self);

for(;;){

SIO_get(...);

--processdata--

TSK_deltatime(TSK_self);

}

}

假设流式IO没有准备好,则该API函数会阻塞(Blocked),任务切换,一段时间后,流式IO数据

准备好了,此时发出READY信号,将本任务置为ready状态,此时TSK_settime会重新记录时间。

6.voidTSK_disable(void)

全局关闭内核调度机制,Busy-Shutting-Down状态。只有当前任务可行,其余所有任务制止。

此函数不会制止中断,所以在中断开场前需要调用此函数保证中断发生时不会发生任务切换。

可以嵌套,但是调用几次TSK_disable,就得相应调用几次TSK_enable

7.voidTSK_enable(void)

全局开启内核调度机制

8.voidTSK_e*it(void)

终止当前任务运行。如果所有任务都被终止,则DSP/BIOS会调用SYS_e*it终止程序。

无论什么时候,任务从顶层函数返回时,都是自动调用此函数。

可以注册一个退出辅助函数voidmyE*itF*n(void)

这样,在任务被设置为TSK_TERMINATED模式之前,会调用这个辅助函数。

9.Ptrenviron=TSK_getenv(TSK_Handletask)

返回任务环境指针,这个指针指向一个该任务可以的全局属性的构造。

假设程序定义多个钩子对象,则HOOK_getenv函数可以获取设置的环境指针。

10.voidTSK_setenv(TSK_Handletask,Ptrenviron)

设置指定任务的环境指针。

假设程序定义多个钩子对象,则HOOK_setenv函数可以为每个钩子和任务对象的组合体设置独立的环境指针。

11.interrno=TSK_geterr(TSK_Handletask)

每个任务对象都有一个包含任务错误号的存储单元。初始值为SYS_OK

12.voidTSK_seterr(TSK_Handletask,interrno)

改变错误号

13.Stringname=TSK_getname(TSK_Handletask)

返回任务的名字。

对于静态对象来说,必须翻开AllocateTaskNameonTarget

对于动态对象来说,TSK_getname返回字段

14.intpriority=TSK_getpri(TSK_Handletask)

返回优先级

15.intoldpri=TSK_setpri(TSK_Handletask,intnewpri)

设置优先级

设置优先级对于TSK_BLOCKED状态任务只是优先级改变,而不会改变状态;

对于TSK_READY状态的任务而言,可能会改变运行状态。

16.STS_Handlests=TSK_getsts(TSK_Handletask)

获得统计对象句柄,以便查看数据

17.voidTSK_sleep(Unsnticks)

暂停任务的时钟个数,此时钟数可能比真实的暂停时钟少一个时钟〔告警时钟〕

18.voidTSK_itick(void)

对告警时钟加1,以便让TSK_sleep或者SEM_pend函数暂停执行的任务恢复到ready。

一些暂停的任务可能会随着告警时钟的增加而超时,从而就绪。

19.voidTSK_tick(void)

对告警时钟加1,以便让TSK_sleep或者SEM_pend函数暂停执行的任务恢复到ready。

一些暂停的任务可能会随着告警时钟的增加而超时,从而就绪。

可以在中断效劳程序和当前任务中调用,后者在控制超时非常有用。

20.Unscurrtime=TSK_time(void)

返回系统告警时钟的当前值。(由于延迟,只能得到一个大概的系统时钟)

21.TSK_Handlecurrtask=TSK_self(void)

返回当前任务对象的句柄

22.voidTSK_stat(TSK_Handletask,TSK_Stat*statbuf)

返回任务的属性参数和状态信息

structTSK_Stat{

TSK_Attrsattrs;//任务参数

TSK_Modemode;

//任务执行模式

Ptrsp;

//任务当前堆栈指针

Unsused;

//任务堆栈曾经使用的最大值

}

注意:任务比HWI和SWI中断优先级要低,所以当任务被中断时,还是返回TSK_RUNNING,

因为中断完成后任务继续运行。

23.voidTSK_yield(void)

强制任务切换,请注意,任务可以被中断,但是,任务之间必须依靠切换来进展,就是说,

即便当前有高优先级任务就绪,它不能被执行,除非切换。

此函数用于任务之间的同步。

(十)任务管理HOOK钩子函数管理模块

HOOK模块管理者一

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论