景's profile聆听卡农,享受生活!PhotosBlogListsMore ![]() | Help |
|
聆听卡农,享受生活!带着聆听卡农的心情享受生活! 6/10/2009 关于44B0无法下载程序的问题前天总算是把板子画完了。博创那块44B0的板子小师弟最近一直在用,说是下载程序不正常了。具体表现为:从十几天之前起,有时候就下不进程序。拔下来放一段时间就又可以下。他怀疑是哪儿接触不良或者虚焊了,把CPU,FLASH,SDRAM通通加焊了一遍,还是没用,最近就完全没反应了。我的PCB也完成了,就决定查查原因。
4/24/2009 关于OPENTCP的一处小bug OPENTCP的整个移植+调试终于完成了,ARP、ICMP、TCP、UDP、HTTP几个常见的协议都没什么问题了,并且也实现了一个简单的网口到串口转换。
所谓“山重水复疑无路,柳暗花明又一村”,我可是深刻地体会到了。把OPENTCP整个搬过来,再把和44B0相关的底层驱动写了之后就扔了三个多月,从上周开始调,看那一堆乱七八糟的问题头都疼,折腾了好几天没什么头绪。再捣腾了两天终于可以PING通了,ARP包、ICMP包收发正常之后,UDP,HTTP,TCP也相继很快都解决了!
不过在最后调试TCP的客户端时一直不通。找了半天原因,最终发现是因为Tcp.c中的tcp_connect函数中有点小bug:
tcp_connect函数的最后三句是:
tcp_sendcontrol(sochandle);
tcp_newstate(soc, TCP_STATE_SYN_SENT); return(sochandle);
即就是调用tcp_sendcontrol函数发送TCP连接申请,接下来将对应TCP连接的SOCKET状态设置为TCP_STATE_SYN_SENT;这样看似乎没什么问题,但是忽略了一种情况,就是发送失败。这儿没有判断调用tcp_sendcontrol函数的返回值。也就是说就算发送失败了,也把SOCKET状态设置为TCP_STATE_SYN_SENT了。而在tcp_connect函数的前面部分有一处会判断SOCKET状态,就是下面这几句: if( (soc->state != TCP_STATE_RESERVED) &&
(soc->state != TCP_STATE_LISTENING) && (soc->state != TCP_STATE_CLOSED) ) {
TCP_DEBUGOUT("Socket on unvalid state to initialize CONNECT\r\n"); return(-1); } 如果发送失败的话,接下来就会将SOCKET状态设置为TCP_STATE_SYN_SENT,然后下次再调用tcp_connect时,就会在上面判断的地方返回。也就不会再发TCP连接申请出去了。所以说,在这种情况下,要成功建立TCP连接,就要第一次调用tcp_connect时“只许成功,不许失败”。但是发送失败的可能性是存在的,因为tcp_sendcontrol函数在逐级向下调用时会调到process_ip_out函数,而在process_ip_out入口处有一个从ARP缓存中获取MAC地址的操作,即: qstruct = arp_find(ipadr, &localmachine, ARP_TEMP_IP); 并且,除了上面提到的,在tcpc_demo_run中判断是否要执行发送TCP连接申请操作处也有问题: if(tcpc_demo_connect)
{
if(tcp_connect(tcpc_demo_soch, TCPC_DEMO_RMT_IP, TCPC_DEMO_RMT_PORT,0)>0) {
tcpc_demo_connect=0; } } 这儿判断的是如果tcp_connect函数返回值大于0的话就将连接操作标志tcpc_demo_connect清零。但是tcp_sendcontrol函数的最后一句返回操作之前是返回SOCKET ID的,即: return(sochandle); 如果申请到的SOCKET对应sochandle为0,那么永远都不会清零tcpc_demo_connect这个标志了,所以如果其它一系列条件满足,就会不断地发送TCP连接申请出去。这里应该把判断条件修改为: if(tcp_connect(tcpc_demo_soch, TCPC_DEMO_RMT_IP, TCPC_DEMO_RMT_PORT, myport) == 0) 然后把tcp_sendcontrol函数返回处按以下提到方式修改: 修改方法:因为OPENTCP中本来tcp_sendcontrol是VOID返回类型的。所以将tcp_sendcontrol的返回类型修改为INT16(16位符号整型),然后在调用tcp_sendcontrol之后判断返回值再决定要不要设置SOCKET的状态。即如下: Result = (INT8)tcp_sendcontrol(sochandle); if (0 == Result) { tcp_newstate(soc, TCP_STATE_SYN_SENT); } return (Result); 4/20/2009 44B0+RTL8019的PING实现过程 今天早上,44B0板子终于可以PING通了,我长出一口气——折腾了这么久,总算看到进展了!
从去年12月份把OPENTCP整个搬过来之后,就大概把驱动的部分重新写了下。因为接下来的三个月是AMP最忙的一段时间,几乎天天加班,所以就没再去实验室。板子虽然在宿舍里,可是也懒得去调,一有时间我都用来补觉了。过了三个多月,板子上落了一层灰。上周回来之后,就又重新拾起来了。打算把已经移植好的协议栈好好调一下。这不调则已,一开始调就发现什么乱七八糟的问题都有,当然最明显的就是首先都PING不通。 因为OPENTCP协议栈里涉及到定时器池的初始化和分配,硬件上我是用44B0的定时器3来实现一个10ms的中断。刚一开始在AXD环境下单步调试,定时器的中断都进不了。开始怀疑是定时器的寄存器设置的问题,对着44B0的datasheet仔细检查了一遍定时器的初始化代码,发现没有不对的地方呀,并且发现在AXD下单步调试的话代码老是跑飞,所以老进不了定时器的中断入口。于是就在定时器中断服务子程序里面加了一个串口输出的操作,然后不用AXD,直接让板子脱机运行,再用超级终端观察显示结果,果然显示正常,说明可以正常进入定时器中断。接下来在网上查了下关于SDRAM的工作原理,得出结论可能是因为SDRAM的初始化对读写时序设置得不精确,本来SDRAM的稳定性就比较差,所以对时序的要求就比较苛刻,读写时序一旦有偏差,再出现一点中断什么的,就会导致在线调试程序跑飞。于是在接下来的调试中我就暂时把定时器中断关掉了,脱机运行的时候再打开。 定时器的问题解决了,接下来就找为什么PING不通的原因了。 PING操作其实就是对应了ICMP包的发送和接收。在第一次PING时因为主机的ARP表里没有目标板网卡的MAC地址表项,于是会先发一个ARP包来解析目标板的MAC地址。但是我发现在主处理循环里面,如果在ARP处理入口处打断点,然后在主机上命令行敲PING命令时根本断不住,并且检测是否接收到数据包的那一段代码都没有反应,也就是说根本没有接收到数据。所以最开始想到的就是8019的初始化有问题,检查了一段时间后发现是因为8019的寄存器定义不对,但是根源还不在此,主要是因为DCR寄存器配置有问题,最初我配置的是16位DMA,一直接收不到数据,改成8位之后就可以接收到主机发送来的数据了,并且也可以进入ARP数据的处理入口了。但还是PING不通。 并且还发现一个奇怪的问题,就是8019的CR寄存器设置换页不成功,比如最初是在第0页上,我想切换到第3页,执行代码outNE2000(CR, 0xe1);然后查看MEMORY,发现对应CR寄存器的存储单元的数据会变成预料中的0xe1,但是只要一执行下一个语句,CR寄存器对应内存单元又会变成0x21,所以读取其它寄存器的值时读出来老是错的,搞得我百思不得其解。在网上搜了下,发现很多人都有这个问题,但是没有人给出答案。最后我意外中发现,只要全速执行,把配置寄存器的语句跳过去,然后再读寄存器的值,读出来就是对的,很诡异!最后我想到的解释就是:因为SDRAM是动态存储的,并且是分页,所以会定时对内存进行刷新,因此单步调的话因为时间的原因就没办法刚好读到准确的值,不知道这种理解对不对,但是目前也没时间去深究这个,所以就先这样理解了。 再折腾了两天,觉得只是这样调试根本看不出什么来,于是抓包看,发现ARP包的发送和接收都是正常的:主机敲PING命令时,先发送一个ARP包给目标板,目标板接收到之后会进行IP地址的判断,然后把自己的MAC地址封装到ARP的响应消息里发给主机,主机也可以接收到,在主机上用命令行敲ARP -A的话可以看到已经有目标板对应的MAC表项了。所以下面就应该是主机发送ICMP包给目标板了,因为ICMP包是属于IP包的,但是单步跟时发现程序根本不进IP消息的处理入口,也就是说收不到ICMP包。这个可就奇怪了,既然ARP包都可以接收和发送,说明硬件上是没有问题的,那会是哪儿不对? 又捣腾了好几天,没捣腾出个所以然来。昨天在网上找了下,也是有很多人有类似的问题,其中有一个人也是发帖子请教大家可以收到ARP包,收不到ICMP包是什么原因。最后自己查出来说是MAC地址写错了。我立马看了一下我的MAC初始化部分,发现没问题呀,在主机上捕获到ARP响应包里的MAC地址就是我设置的MAC,MAC似乎是没问题的。最后突然冒出来一个想法,难道是顺序搞反了?因为ARP响应包里的是没错,但那只是一个显示的先后顺序的问题,但是在MAC初始化时对于PAR寄存器的设置,顺序可就关系大了。于是马上检查了一下,果然是设置MAC寄存器时把顺序搞反了。也就是说MAC地址的第一个字节被写到PAR5里面,第六个字节反而被写到了PAR0里。没错,应该就是这个原因! 今天早上去实验室把MAC初始化的地方改了过来,命令行敲PING,果然就捕获到ICMP响应消息了!看到命令行显示出的结果,真是大快人心! 暂时松一口气,接下来就是调TCP,UDP等一系列应用相关协议了,希望不会再有这么多乱七八糟的问题了! 最后送自己一句话:革命尚未成功,同志还需努力! 4/14/2009 ARM JTAG仿真器调试方法之SDRAM篇(转载) 之前介绍了使用ARM JTAG仿真器将映像文件加载到ARM处理器内部SRAM中进行程序调试的方法,而在实际操作中,将映像文件加载到外部SDRAM中进行调试的方式更为常见。
要把映像文件加载到SDRAM中,除了要正确设置好映像文件的RO段基地址外(对于一个加载时域和运行时域相同的映像文件来说,RO段基地址实际上就是该映像文件在存储空间的起始地址),更关键的是要对SDRAM进行初始化。因为在上电时,SDRAM是没有被初始化的,所谓初始化SDRAM,就是要设置处理器的SDRAM空间以及读写SDRAM的时序参数,因而SDRAM在初始化之前是不能进行读写操作的。
对于PXA270处理器,初始化SDRAM的工作通过配置存储控制器寄存器来完成,这些寄存器包括MDCNFG,MDREFR,MDMRS。
由于这些寄存器都映射到了某一存储空间地址,因而可以在AXD的命令行窗口(System Views->Command Line Interface [Alt+L])中使用setmem命令来对寄存器进行配置。setmem命令(简写为smem)可以为存储空间的某一地址单元指定值。例如“setmem 0x48000000 0xac9 32”的含义就是将常数0xac9保存到地址为0x48000000的字中(一个字32bit)。实际上,通过查阅Intel PXA27x Processor Family Developer’s Manual可知,0x48000000正是寄存器MDCNFG的地址,因而这条命令实质上完成了对MDCNFG寄存器的配置,使能SDRAM partition 0,使用32bit宽的SDRAM数据总线,9位列地址,13位行地址,SDRAM内部采用4 bank设计,tRP=3,CL=3,tRCD=3,tRAS=7,tRC=10,采用普通寻址模式;不使用SDRAM partition 2/3。具体设置要根据实际所使用的SDRAM芯片进行。
因此,可使用3~4条setmem命令初始化SDRAM,之后就可以正确地将映像文件加载到SDRAM中运行了。顺便提一句,PXA270有两种SDRAM存储模式,一种是小空间模式,支持4个64M的partition共计256M字节,起始地址为0xa0000000;另一种是大空间模式,支持4个256M的partition共计1GB,起始地址为0x80000000。应根据实际情况设置正确的RO BASE地址。
关于使用ob命令自动初始化SDRAM:
由于每次上电后往SDRAM加载映像时都需要对其进行初始化,手工输入多条命令有时是很繁琐的。这时,可以把初始化SDRAM的命令序列保存在一个*.ini文本文件中(也可以是*.txt文件),每条命令占一行。然后在AXD命令行窗口使用obey命令调用该*.ini文件,就可以将文件中的命令顺序执行,继而完成SDRAM的初始化。
例如,将SDRAM初始化命令序列保存在PXA270.ini文件中,执行命令:
ob $PATH/PXA270.ini
就可自动执行初始化SDRAM的命令。其中,ob是obey的简写,$PATH是PXA270.ini文件的绝对路径。
更多AXD命令和内容可以参考ADS手册之《AXD and armsd Debuggers Guide》。
启动AXD时自动初始化SDRAM:
感谢网友Garfield的指点,他提出了在硬件平台不变的情况下,在启动AXD时自动初始化SDRAM的一劳永逸的办法,经笔者证实,该方法确实是可行的。
具体办法如下:
将初始化SDRAM的命令序列保存为一个*.txt文本文件(可以直接将上述的*.ini文件后缀改为.txt),然后在AXD的主窗口下选择菜单Options->Configure Interface...,在Session File一页中选择“Run Configuration Script”,将该.txt文本文件作为一个脚本加进来,确定。这样以后每次启动AXD时,就会自动运行该脚本来完成对SDRAM的初始化。
附:每次系统重新上电或硬件复位后都需要重新初始化SDRAM才能把映像文件加载到SDRAM。可以设置在AXD启动时自动对SDRAM进行初始化,见“启动AXD时自动初始化SDRAM”部分。有时候AXD启动后需要重新配置,这是ADS自身的问题,主要是看启动后在Command Line Interface窗口有没有出现初始化SDRAM的命令,另外在AXD的源码窗口右键Interleave Disassembly,看各条代码在SDRAM中对应地址的内容是否为正确的机器码,来检查映像文件是否成功加载。
4/12/2009 华为半年前天,我半年的实习期终于还是结束了。下班后在大家的告别声中离开了公司。从去年十月六日入部门一直到昨天离开,我在华为经历了整整半年零四天。在这半年零四天里,收获了许多,这许多许多只能用“一言难尽”来形容。 过了十几年的学生生活,终于第一次体验到了工作的感觉。在学校,包括上大学前,本科一直到研究生实习前,我都是属于“好学生”的范围,感觉自己还是有点小聪明的,本科时也没有那么疯狂地上自习什么的,照样也能拿着奖学金,最后保研。并且从大三起跟着老赵做点电子设计之类的东西,动手能力还是能说得过去的。但就是感觉缺少了点什么,渐渐地我明白了,我缺少的就是社会经验和经历。 去年九月份华为来学校招实习生的时候,因为知道老赵不会同意,当时只是抱着积累经验的想法去听了宣讲会,填了简历又参加了面试,可是面试通过后,我的态度开始变得坚决,急切地想要体验一下工作到底是什么样的。从面试通过后花了将近二十多天的时间终于说服了老赵,同意我去实习六个月。 2008年9月29号,我们去报了到,搞了一天的培训,基本上都是关于信息安全之类的。国庆过后,在10月6号,正式入部门。最初我是被分到接入网硬件开发部的,说是硬件,其实基本上也是纯软件的东西,跟我在学校做的几乎没什么关系。在第一周,学习了一些通信的基础知识,因为不是通信专业,很多东西都觉得很陌生。不过,在硬件开发部也就呆了一周多,因为AMP部门缺人,我就和一名西工大的实习生搬到了三楼,她就是石苗——比我早一个月进公司,跟我同甘共苦了几个月,最后和我同时离开公司的好姐妹。我对她印象最深的就是,第一次和她一块儿在海星餐厅吃饭,看着她风卷残云般塞完了那一大碗面和一个葱油饼,再看看我的碗,才吃了几口,顿时心里惊叹:“真见着比我和娇娇还能吃的女生了!!!”…… 我们俩搬到三楼后,因为AMP的人都还在深圳,所以就暂时挂在SSMP下,然后遇到了我的第二位师傅卢玮。在SSMP的那段时间,学了很多软件类的东西,比如在C语言和编程规范方面有了很大的提升。在学校的时候,一直觉得自己的编程功底还是不错的,到SSMP之后,我才知道C语言还可以用得那么灵活,自己真是见识浅薄了!再过了十几天,AMP的人就陆陆续续回到西安了,我和石苗的工作也就逐渐步上正轨了。 实习前,一直觉得肚子里还是有些墨水,在学校还是有点小骄傲的资本的。进公司之后,才发现自己其实几乎就是一张白纸——学校和公司是两片完全不同的天地!刚入部门,似乎什么都不懂,什么都得从头学。在学校里做过的那些东西都成了玩具,没有实用性可言。记得第一次看到部门上千万行的代码时,我完全懵了,有一种老虎吃天不知道从哪儿下爪的感觉。想想自己在学校里写的那些,简直就是小CASE中的小CASE了。以前也觉得自己会使用的工具软件还不少,理的ADS,IAR,MATLAB,PROTEL什么的,文的PHOTOSHOP,PREMIER什么的,有的谈不上精通,但至少都能耍一耍。入部门后才发现,工具软件太多了,只要有需要,你就得立马学,并且得在最短的时间内上手。逐渐地,我无比深刻地体会到了:无论什么时候都得要保持一颗谦虚向上的心,这样才能不断进步和成长! 过了一段时间,在同事的指导和帮助下,觉得部门代码不再那么庞大、难以理解了,同时也掌握了很多常用工具软件的使用。 在第三个月的时候,我正式承担了自己的第一份开发工作。比较好笑的是,接到任务之后,我看了一天的代码,大概地熟悉了一下流程什么的,就计划在第二天开始编码了。结果在第二天的早会上才知道,我们要按照一个严格的流程来:无论是写文档、编码调试还是交付,都得要遵循一定的流程和规范,完全不像以前在学校里那种天马行空般地代码想咋写就咋写,总结想写就写,不想写就拉倒(一般情况下都不写)。 经过第三个月,我很辛苦地完成了自己的第一份开发任务,完全没有之前想像的那么顺利。第四个月,我们开始了一系列关于敏捷开发的培训,为下一个版本的开发做准备。接下来的两个多月,就是我进公司后过得最累、但也是最有意义的一段时间了。因为是第一次实行敏捷开发,大家都在摸索,几乎天天加班。我几乎每天都是九点半以后回。难为娇娇同学给我打了好几个月的水,有一次她们两个白天也有事回晚了没打着水,晚上偷偷用热得快被楼管阿姨抓个正着,骂了个狗血淋头,最后还写了检讨,最背的是还赶上老爸第二天来西安开会,楼管阿姨还向老爸告我的状,害得老爸还给楼管道了半天的歉,真是狼狈到极点! 其实,在这半年里感觉最大的收获还是人,他(她)们对我来说既是最好的同事又是最好的朋友!…… 师傅赵——我在华为的第一任师傅。走起路来慢慢腾腾,但业务能力很强,喜欢在午睡前玩会儿连连看; 师傅卢——我的第二任师傅,软件开发部的技术牛人。谁有问题都找他,每天在自己座位上呆的时间小于在别人座位上的时间。敲键盘跟玩打地鼠一样,噼哩啪啦,速度超快!以至于我经常怀疑他的键盘寿命不超过三个月; 薛亚波——最容易相处的主管,和大家打成一片,玩的时候一点儿都不像领导,每次集体活动他都承担跑腿的角色。我印象最深的就是那次大家滑玩冰后,在我们学校后街的“小眼睛辣汁肉夹馍”吃饭。十四个人浩浩荡荡地挤进了那个小饭馆。大家呼啦一下都找了位子坐了下来,他就跑前跑后地统计谁要吃什么。饭毕,又在徐家庄入口领着大家吃菠萝。但是玩归玩,工作上也是丝毫不含糊,如果大家哪儿做得不好,他也会毫不留情地K你一顿; 李洪海——敏捷开发我们组的小头头,相当爱唠叨,但是对人特别好。AMP的人都比较内敛,开会时不喜欢发言,每次开会冷场都是他冒出一两句来救场。 小强——从SSMP挖过来的技术牛人。尽管已经被挖过来了,每天还是有很多原部门的人跑过来求他解决问题。记得当初他刚来AMP,因为不熟,大家都和他话不多,组织个活动什么的,他跑来问,我们都不愿意去,他经常是热脸贴我们的冷屁股。最后熟了之后,大家就离不开他了,出现棘手的问题首先想到的解决方法就是——“找小强”; 雷军——AMP的顶头上司,人如其名,做事雷厉风行!喜欢游泳。第一次见他有“笑面虎”的感觉,接触久了就会觉得挺好相处,并且能力不是一般得强,似乎什么都知道!不过有一件事他应该不知道:有一段时间他去深圳,我偷喝了他放在桌上的八宝粥,还和其他几个人瓜分了他的饼干! 丁伟——又一个工作狂人,相处的时间只有短短的几周,他大部分时间都在深圳。说话比较直,据说他几乎跟AMP的每个人都因为工作吵过。不过是属于典型的对事不对人型的,吵完后立马没事。我做第一个特性开发时经常烦他。当时第一次开发,PCLINT一大堆错误,我实在搞不定了就把他请过来,害他给我捣腾了半天,结果最后是因为头文件里漏写了个分号,气得他抓狂!嘿嘿!——个人感觉他挺好玩的; 李永军——从VSP挖过来的牛人,羽毛球冠军,摄影也很棒,全面发展的人才!操一口中国式英语,“什么意思”就是“what mean”; 聂欣——美女测试经理,第一次见她觉得很文静,不大说话。接触一两次后我这个感觉完全被颠覆了——她的口才貌似AMP没有人可以拼得过(讲话跟打机关枪一样),并且能力很强,长得漂亮又有气质,很佩服她! 海霞&吕勇胜——也是测试部的,两个人都是属于那种偶尔冒出一两句话能把大家都逗笑,但是他(她)们自己还一本正经,不觉得好笑的类型。工作态度相当认真,尤其是吕勇胜同学,认真到经常能把别人搞得抓狂; 鲁扬——我的最后一任师傅,和我海拔差不多,我们师徒俩都是属于“浓缩型”的。她刚从深圳回来时,不大说话,也不大笑,我还挺怕她,其实也是因为不熟的原因。相处了十多天之后就觉得“还是师傅对我最好!” 陈亮——被石苗冠名“小屁孩”,部门里唯一一个比我小的,比我晚一个月进公司。因为年龄的原因,在学校一向被鄙视惯了,好不容易有个比自己小的,终于有鄙视的对象了,我和石苗成天以欺负他为乐; 李莹——认识最晚但也是和我关系最铁的一个,也是西电毕业的,典型的西电女生性格,好像比我早四届。现在就住在我们学校家属院,离得很近,以后还可以经常找她玩。不知道什么原因,她吃饭经常能吃出奇怪的东西。一次大家在苏记聚餐,她就从土豆块里吃出一根头发,把服务员叫过来后还恶狠狠地扬言“我很生气,后果很严重”!被我封为“华为第一大恶人(注:恶心的“恶”); 韦亚超——从核心网测试调过来的,跟谁都能聊得来。成天叫我“可神经”,被我封为“华为第二大恶人”。敏捷开发讲究结对编程,他跟李莹一个结对,两个人就是一对活宝,成天斗嘴,互相贬低; 刘辰——对于我来说最应该提到的人——我的“黄金搭档”,南航毕业,08年5月份才进公司,能力很强,尤其是定位问题的能力超强!属于说少做多型的。偶尔会冒出一两句很有哲理的话。喜欢说“这个太诡异了!”,还喜欢说“水至清则无鱼”。第一次见他没什么好感,用师傅鲁扬的一句话“那个人怎么长得凶巴巴的”,就是觉得他老不说话,一个人闷在那儿,别人给他说话也不大搭理。敏捷开发我们俩一个结对,不过每次都是他做2/3,我做1/3(沾了他不少光),他最常对我说的就是:“这个你不用管了,我来搞吧,你把那个XX弄一下。”——结对之后发现其实他很细心,很有责任感,并且挺好玩,也没那么“凶巴巴”,是个很值得深交的朋友! 经历了这半年,我已经不再是当初那个看到中午大家很壮观地席地而睡都觉得很好玩的新员工了。这半年,学到了许多,成长了许多,不知道有没有留下许多。离开公司后,有一种回到原点的感觉,但似乎已经不大适应学校的生活了。每天早上七点一到,准时就醒,往日的“睡神”一去不复返!晚上做梦都是if什么,else什么又for什么的。不过,目前最重要的还是要迅速回到以前的状态,好好过完在学校的这最后一年。 除了以上提到的,还有很多给了我莫大指导和帮助的人。不管以后会怎么样,在华为的这半年,还有半年中遇到的这些人都将成为我永远的、最最宝贵的财富!希望他(她)们都能在以后的工作和生活中事事顺心,笑口常开!!!^-^ |
|||||
|
|