当前位置:首页 > 调试
  • 博通平台调试LOG的常用抓取方法

    开发调试中的办法非常多,LOG是其中重要的一个方法,一些常见的LOG的抓取办法(主要针对QUALCOMM平台,未经详细整理): 1.ADB查看或保存kernel的启动LOG: kernel log: adb shell dmesg > d:kerneltestlog.txt tips :dmesg -n 8               //设置log的等级 #define KERN_EMERG""/* system is unusable*/ #define KERN_ALERT""/* acTIon must be taken immediately*/ #define KERN_CRIT""/* criTIcal condiTIons*/ #define KERN_ERR""/* error condiTIons*/ #define KERN_WARNING""/* warning conditions*/ #define KERN_NOTICE""/* normal but signIFicant condition*/ #define KERN_INFO""/* informational*/ #define KERN_DEBUG""/* debug-level messages*/ dmesg -s 81920              //设置LOG的Buffer,默认的buffer是8192 2.smem log:     1>、用trace32。trace32无疑是强大的,几乎可以做任何debug的事情,有高通代码的兄弟可以在AMSSproducts 76XX oolsdebug目录下找到smemlog.cmm和smem_log.pl这两个文件,可以dump出log. Run “do toolsdebugsmemlog.cmm” from Trace32 Run “perl smem_log.pl > smemlog.txt”     2>、没有trace32的兄弟也不要灰心,google为我们提供了强大的adb工具。命令如下:     adb shell     mkdir /data/debug     mount -t debugfs debugfs /data/debug     cd /data/debug/smem_log     cat dump_sym    可以给大家看一下抓下来的部分log    3.各种log(实际也包括第1种kernel的启动日志): 很多人经常搞不清楚各种日志文件的作用,什么时候抓这些文件,其实如果你分不清楚的话                最好一起抓了,至少你要分清楚有哪些日志文件需要抓。     log文件分为实时打印的,还有状态信息的两种 实时打印的主要有:logcat main,logcat radio,logcat events,tcpdump,还有高通平台的还会有QXDM日志     状态信息的有:adb shell dmesg,adb shell dumpstate,adb shell dumpsys,adb bugreport     讲解一下各自作用:     通过DDMS抓的其实跟用dos批处理抓的一样都是logcat的日志文件,ddms抓的通常是main缓存中的,就是应用程序打印的日志文件。不过 ddms好处在于能够实时看到带有颜色的,如果是用dos批处理只能重定向到文件,到抓完之后才能够看到,不是实时的。     DDMS是调试应用的最重要的一个LOG工具了。     adb logcat -b main -v time>app.log  打印应用程序的log     adb logcat -b radio -v time> radio.log 打印射频相关的log,SIM STK也会在里面,modem相关的ATcommand等,当然跟QXDM差的很远了。     adb logcat -b events -v time  打印系统事件的日志,比如触屏事件。。。     tcpdump 是很有用的,对于TCP/IP协议相关的都可以使用这个来抓,adb shell tcpdump -s 10000 -w /sdcard/capture.pcap,比如抓mms下载的时候的UA profile,browser上网的时候,使用proxy的APN下载,streaming的相关内容包括UA profile等。     最后是高通平台的QXDM,不管是不是Android,只要使用高通芯片,都会对它很熟悉,当然了,不是高通的芯片就不用提它了。这个不多讲,内容丰富,射频,电话,上网,...凡是高通提供的解决方案,这个都可以抓。     状态信息:其实一个就够了,那就是bugreport(命令adb bugreport>bugreport.log)。里面包含有dmesg,dumpstate和dumpsys。dmesg(命令adb shell dmesg > ldmesg_kernel.log)是kernel的log,凡是跟kernel相关的,比如driver出了问题(相机,蓝牙,USB,启动,等等吧)。 dumpstate是系统状态信息,里面比较全,包括手机当前的内存信息、cpu信息、logcat缓存,kernel缓存等等。adb shell dumpsys这个是关于系统service的内容都在这个里面,这个命令还有更详尽的用法,比如db shell dumpsys meminfo system是查看system这个process的内存信息。 还有其他的比如PV的log,一般都是开发人员自己写的,可能让你放到sd卡里面,其他的不足或需要补充的期望您的指导。 4.查看用户空间的WAKELOCK: cat /sys/power/wake_lock cat /proc/wakelocks 5.MODEM端的LOG最主要的是QXDM,这个用QUALCOMM平台的人都知道; 手机在MODEM端crash时的QXDM LOG的获取通过如下办法 crash F3 log: To get F3 trace from Trace32 1>.Run recover_f3.cmm or getf3trace.cmm with Trace32 connected or the Trace32 Simulator when the appropriate ELF/ramdump is loaded 2>.Run “perl FormatTrace32F3Trace.pl trace0001.txt > f3.txt”; this generates a nicer looking f3.txt than raw trace0001.txt To get F3 trace from trace data stored to EFS 1>.Get the file of F3 saving from EFS by using QPST EFS Explorer err_f3_index00.F3for MSM6xxx apps_err_f3_index00.f3, modem_err_f3_index00.F3for MSM7xxx 2>.Run recover_f3.cmm or process_efs_trace_file.cmm 3>.Run “perl FormatTrace32F3Trace.pl trace0001.txt > f3.txt” test 1>.run trace32 simulate,load elf,do do recover_f3.cmm 2>.perl FormatT32F3Trace.pl f3tokens.txt msg_hash.txt > f3log.txt    (Linux,windows should intall perl.)(QSRMessageHash.qsr as msg_hash.txt) 上面都是直接可以使用的LOG获取办法;另外还有一些LOG的获取办法需要自己稍微修改,只列举几个我曾经使用过的例子。 1.LCD,这个是在bootloader使用的。       在MODEM或Android的APPSBL里面可以直接写LOG到LCD,这个需要自己转换字库点阵到位图,还有位图到LCD的画屏。       在linux的kernel也可以指定console到LCD。直接查看kernel的启动LOG。 2.FLASH文件系统,这个使用当然必须在文件系统OK后。这个我是在USB失效时,或者遇到抓取一些不能使用USB条件的LOG:        MODEM端可以写LOG文件到EFS。        linux端可以写LOG文件到SD卡。 3.串口。这个我也是把linux kernel的console指定到qualcomm的hs uart2上,抓取kernel的启动日志的

    时间:2020-05-26 关键词: 高通 调试

  • 电路调试的一些方法,你真的知道吗?

    电路调试的一些方法,你真的知道吗?

    电路调试有一些什么步骤,你真的知道吗?调试是初级电子工程师在初级阶段必须学会的。所以我们强烈推荐本篇文章给大家。 实践表明,一个电子装置,即使按照设计的电路参数进行安装,往往也难于达到预期的效果。这是因为人们在设计时,不可能周全地考虑各种复杂的客观因素(如元件值的误差、器件参数的分散性、分布参数的影响等),必须通过安装后的测试和调整,来发现和纠正设计方案的不足,然后采取措施加以改进,使装置达到预定的技术指标。因此,调试电子电路的技能对从事电子技术及其相关领域工作的人员来说,是不应缺少的。 调试的常用仪器有:稳压电源、万用表、示波器、频谱分析仪和信号发生器等。电子电路调试包括测试和调整两个方面。调试的意义有二:一是通过调试使电子电路达到规定的指标;二是通过调试发现设计中存在的缺陷并予以纠正。 1、电子电路调试的一般步骤 传统中医看病讲究“望、闻、问、切”,其实调试电路也是如此。 首先“望”,即观察电路板的焊接如何,成熟的电子产品一般都是焊接出的问题;第二“闻”,呵呵,这个不是说先把电路板闻下,而是说通电后听电路板是否有异常响动,不该叫的叫了,该叫的不叫;第三“问”,如果是自己第一次调试,不是自己设计的要问电源是多少?别人是否调过?有什么问题?第四“切”,元器件有没焊全、芯片焊接是否正确、不易观察的焊点是否焊好?一般调试前做好这几步就可发现不少问题。 根据电子电路的复杂程度,调试可分步进行:对于较简单系统,调试步骤是:电源调试→单板调试→联调。对于较复杂的系统,调试步骤是:电源调试→单板调试→分机调试→主机调试→联调。由此可明确三点:(1) 不论简单系统还是复杂系统,调试都是从电源开始入手的;(2) 调试方法一般是先局部(单元电路)后整体,先静态后动态;(3) 一般要经过测量→调整→再测量→再调整的反复过程;对于复杂的电子系统,调试也是一个“系统集成”的过程。 在单元电路调试完成的基础上,可进行系统联调。例如数据采集系统和控制系统,一般由模拟电路、数字电路和微处理器电路构成,调试时常把这3部分电路分开调试,分别达到设计指标后,再加进接口电路进行联调。联调是对总电路的性能指标进行测试和调整,若不符合设计要求,应仔细分析原因,找出相应的单元进行调整。不排除要调整多个单元的参数或调整多次,甚至有修正方案的可能。 2、电子电路调试的具体步骤 (1) 通电观察:通电后不要急于测量电气指标,而要观察电路有无异常现象,例如有无冒烟现象,有无异常气味,手摸集成电路外封装,是否发烫等。如果出现异常现象,应立即关断电源,待排除故障后再通电。 (2) 静态调试:静态调试一般是指在不加输入信号,或只加固定的电平信号的条件下所进行的直流测试,可用万用表测出电路中各点的电位,通过和理论估算值比较,结合电路原理的分析,判断电路直流工作状态是否正常,及时发现电路中已损坏或处于临界工作状态的元器件。通过更换器件或调整电路参数,使电路直流工作状态符合设计要求。 (3) 动态调试:动态调试是在静态调试的基础上进行的,在电路的输入端加入合适的信号,按信号的流向,顺序检测各测试点的输出信号,若发现不正常现象,应分析其原因,并排除故障,再进行调试,直到满足要求。 测试过程中不能仅凭感觉或印象,要始终借助仪器观察。使用示波器时,最好把示波器的信号输入方式置于“DC”挡,通过直流耦合方式,可同时观察被测信号的交、直流成分。通过调试,最后检查功能块和整机的各种指标(如信号的幅值、波形形状、相位关系、增益、输入阻抗和输出阻抗、灵敏度等)是否满足设计要求,如必要,再进一步对电路参数提出合理的修正。 3、电子电路调试中的若干问题 (1) 根据待调试系统的工作原理(原理图和PCB)拟定调试步骤和测量方法,确定测试点,并在图纸上和板子上标出位置,画出调试数据记录表格等。 (2) 搭设调试工作台,工作台配备所需的调试仪器,仪器的摆设应操作方便,便于观察。学生往往不注意这个问题,在制作或调机时工作台很乱,工具、书本、衣物等与仪器混放在一起,这样会影响调试。特别提示:在制作和调试时,一定要把工作台布置的干净、整洁。这便是“磨刀不误砍柴工”。 (3) 对于硬件电路,应为被调试系统选择测量仪表,测量仪表的精度应优于被测系统;对于软件调试,则应配备微机和开发工具。 (4) 电子电路的调试顺序一般按信号流向进行,将前面调试过的电路输出信号作为后一级的输入信号,为最后统调创造条件。 (5) 选用可编程逻辑器件实现的数字电路,应完成可编程逻辑器件源文件的输入、调试与下载,并将可编程逻辑器件和模拟电路连接成系统,进行总体调试和结果测试。 (6) 在调试过程中,要认真观察和分析实验现象,做好记录,保证实验数据的完整可靠。 4、调试前的工作 电路安装完毕,通常不宜急于通电,应该先认真检查一下。 检查内容包括: (1) 连线是否正确:检查电路连线是否正确,包括错线(连线一端正确,另一端错误)、少线(安装时完全漏掉的线)和多线(连线的两端在电路图上都是不存在的)。 查线的方法通常有两种:1) 按照电路图检查安装的线路:这种方法的特点是,根据电路图连线,按一定顺序逐一检查安装好的线路,由此可比较容易地查出错线和少线。2) 按照实际线路来对照原理电路进行查线:这是一种以元件为中心进行查线的方法。把每个元件(包括器件)引脚的连线一次查清,检查每个去处在电路图上是否存在,这种方法不但可以查出错线和少线,还容易查出多线。 为了防止出错,对于已查过的线通常应在电路图上做出标记,最好用指针式万用表“Ω×1”挡,或数字式万用表“Ω挡”的蜂鸣器来测量,而且应直接测量元器件引脚,这样可以同时发现接触不良的地方。 (2) 元器件安装情况 检查元器件引脚之间有无短路;连接处有无接触不良;二极管、三极管、集成器件和电解电容极性等是否连接有误。 (3) 电源供电(包括极性)、信号源连线是否正确。 (4) 电源端对地是否存在短路。 若电路经过上述检查,并确认无误后,就可转入调试。 5、调试方法 调试包括测试和调整两个方面。 所谓电子电路的调试,是以达到电路设计指标为目的而进行的一系列的测量→判断→调整→再测量的反复进行过程。为了使调试顺利进行,设计的电路图上最好标明各点的电位值,相应的波形图以及其它主要数据。调试方法通常采用先分调后联调(总调)。 我们知道,任何复杂电路都是由一些基本单元电路组成的,因此,调试时可以循着信号的流向,逐级调整各单元电路,使其参数基本符合设计指标。这种调试方法的核心是:把组成电路的各功能块(或基本单元电路)先调试好,并在此基础上逐步扩大调试范围,最后完成整机调试。采用先分调,后联调的优点是:能及时发现问题和解决问题。新设计的电路一般采用此方法。 对于包括模拟电路、数字电路和微机系统的电子装置更应采用这种方法进行调试。因为只有把三部分分开调试后,分别达到设计指标,并经过信号及电平转换电路后才能实现整机联调。否则,由于各电路要求的输入、输出电压和波形不匹配,盲目进行联调,就可能造成大量的器件损坏。 除了上述方法外,对于已定型的产品和需要相互配合才能运行的产品也可采用一次性调试。 6、调试中的注意事项 调试结果是否正确,很大程度上受测量正确与否和测量精度的影响。为了保证调试的效果,必须减小测量误差,提高测量精度。为此,需注意以下几点: (1) 正确使用测量仪器的接地端 凡是使用地端接机壳的电子仪器进行测量时,仪器的接地端应和放大器的接地端连接在一起,否则仪器机壳引入的干扰不仅会使放大器的工作状态发生变化,而且将使测量结果出现误差。根据这一原则,调试发射极偏置电路时,若需测量VCE,不应把仪器的两端直接接在集电极和发射极上,而应分别对地测出VC、VE,然后将二者相减得VCE。若使用干电池供电的万用表进行测量,由于电表的两个输入端是浮动的,所以允许直接跨接到测量点之间。 (2) 测量电压所用仪器的输入阻抗必须远大于被测处的等效阻抗 若测量仪器输入阻抗小,则在测量时会引起分流,给测量结果带来很大误差。 (3) 测量仪器的带宽必须大于被测电路的带宽 例如:MF-20型万用表的工作频率为20~20000 Hz。如果放大器的fh =100 kHz,我们就不能用 MF-20来测试放大器的幅频特性,否则,测试结果就不能反映放大器的真实情况。 (4) 要正确选择测量点 用同一台测量仪器进行测量时,测量点不同,仪器内阻引进的误差大小将不同。例如,对于图1所示电路,测C1点电压VC1时,若选择e2为测量点,测得VE2,根据VCl=VE2+VBE2求得的结果,可能比直接测Cl点得到的VC1的误差要小得多。所以出现这种情况,是因为Re2较小,仪器内阻引进的测量误差小。 (5) 测量方法要方便可行 需要测量某电路的电流时,一般尽可能测电压而不测电流,因为测电压不必改动被测电路,测量方便。若需知道某一支路的电流值,可以通过测取该支路上电阻两端的电压,经过换算而得到。 (6) 调试过程中,不但要认真观察和测量,还要善于记录 记录的内容包括实验条件、观察的现象、测量的数据、波形和相位关系等。只有有了大量可靠的实验记录并与理论结果加以比较,才能发现电路设计上的问题,完善设计方案。 7、调试时出现故障的解决方法 要认真查找故障原因,切不可一遇故障解决不了就拆掉线路重新安装。因为重新安装的线路仍可能存在各种问题,如果是原理上的问题,即使重新安装也解决不了问题。我们应当把查找故障,分析故障原因,看成一次好的学习机会,通过它来不断提高自己分析问题和解决问题的能力。 (1) 检查故障的一般方法 故障是不期望但又不可避免的电路异常工作状况。分析、寻找和排除故障是电气工程人员必备的实际技能。对于一个复杂的系统来说,要在大量的元器件和线路中迅速、准确地找出故障是不容易的。一般故障诊断过程,就是从故障现象出发,通过反复测试,做出分析判断,逐步找出故障原因的过程。 (2) 故障现象和产生故障的原因 1) 常见的故障现象:放大电路没有输入信号,而有输出波形。放大电路有输入信号,但没有输出波形,或者波形异常。串联稳压电源无电压输出,或输出电压过高且不能调整,或输出稳压性能变坏、输出电压不稳定等。振荡电路不产生振荡。计数器输出波形不稳,或不能正确计数。收音机中出现“嗡嗡”交流声和“啪啪”的汽船声等。以上是最常见的一些故障现象,还有很多奇怪的现象,在这里就不一一列举了。 2) 产生故障的原因:故障产生的原因很多,情况也很复杂,有的是一种原因引起的简单故障,有的是多种原因相互作用引起的复杂故障。因此,引起故障的原因很难简单分类。这里只能进行一些粗略的分析。 对于定型产品使用一段时间后出现故障,故障原因可能是元器件损坏,连线发生短路或断路(如焊点虚焊、接插件接触不良、可变电阻器、电位器、半可变电阻等接触不良、接触面表面镀层氧化等),或使用条件发生变化(如电网电压波动,过冷或过热的工作环境等)影响电子设备的正常运行。 对于新设计安装的电路来说,故障原因可能是:实际电路与设计的原理图不符;元器件焊接错误、元器件使用不当或损坏;设计的电路本身就存在某些严重缺点,不满足技术要求;连线发生短路或断路等。 仪器使用不正确引起的故障,如示波器使用不正确而造成的波形异常或无波形,接地问题处理不当而引入干扰等。 各种干扰引起的故障。 (3) 检查故障的一般方法 查找故障的顺序可以从输入到输出,也可以从输出到输入。查找故障的一般方法有: 1) 直接观察法:直接观察法是指不用任何仪器,利用人的视、听、嗅、触等作为手段来发现问题,寻找和分析故障。直接观察包括不通电检查和通电观察。 检查仪器的选用和使用是否正确;电源电压的等级和极性是否符合要求;电解电容的极性、二极管和三极管的管脚、集成电路的引脚有无错接、漏接、互碰等情况;布线是否合理;印刷板有无断线;电阻电容有无烧焦和炸裂等。通电观察元器件有无发烫、冒烟,变压器有无焦味,电子管、示波管灯丝是否亮,有无高压打火等。 此法简单,也很有效,可作初步检查时用,但对比较隐蔽的故障无能为力。 2) 用万用表检查静态工作点 电子电路的供电系统,半导体三极管、集成块的直流工作状态(包括元、器件引脚、电源电压)、线路中的电阻值等都可用万用表测定。当测得值与正常值相差较大时,经过分析可找到故障。顺便指出,静态工作点也可以用示波器“DC”输入方式测定。用示波器的优点是:内阻高,能同时看到直流工作状态和被测点上的信号波形以及可能存在的干扰信号及噪声电压等,更有利于分析故障。 3) 信号寻迹法 对于各种较复杂的电路,可在输入端接入一个一定幅值、适当频率的信号(例如,对于多级放大器,可在其输入端接入 f=1000 Hz的正弦信号),用示波器由前级到后级(或者相反),逐级观察波形及幅值的变化情况,如哪一级异常,则故障就在该级。这是深入检查电路的方法。 4) 对比法 怀疑某一电路存在问题时,可将此电路的参数与工作状态相同的正常电路的参数(或理论分析的电流、电压、波形等)进行一一对比,从中找出电路中的不正常情况,进而分析故障原因,判断故障点。 5) 部件替换法 有时故障比较隐蔽,不能一眼看出,如这时你手头有与故障仪器同型号的仪器时,可以将仪器中的部件、元器件、插件板等替换有故障仪器中的相应部件,以便于缩小故障范围,进一步查找故障。 6) 旁路法 当有寄生振荡现象时,可以利用适当容量的电容器,选择适当的检查点,将电容临时跨接在检查点与参考接地点之间,如果振荡消失,就表明振荡是产生在此附近或前级电路中。否则就在后面,再移动检查点寻找之。应该指出的是,旁路电容要适当,不宜过大,只要能较好地消除有害信号即可。 7) 短路法 就是采取临时性短接一部分电路来寻找故障的方法。短路法对检查断路性故障最有效。但要注意对电源(电路)是不能采用短路法的。 8) 断路法 断路法用于检查短路故障最有效。断路法也是一种使故障怀疑点逐步缩小范围的方法。例如,某稳压电源因接入一带有故障的电路,使输出电流过大,我们采取依次断开电路的某一支路的办法来检查故障。如果断开该支路后,电流恢复正常,则故障就发生在此支路。 实际调试时,寻找故障原因的方法多种多样,以上仅列举了几种常用的方法。这些方法的使用可根据设备条件,故障情况灵活掌握,对于简单的故障用一种方法即可查找出故障点,但对于较复杂的故障则需采取多种方法互相补充、互相配合,才能找出故障点。 在一般情况下,寻找故障的常规做法是:先用直接观察法,排除明显的故障。再用万用表(或示波器)检查静态工作点。信号寻迹法是对各种电路普遍适用而且简单直观的方法,在动态调试中广为应用。 应当指出,对于反馈环内的故障诊断是比较困难的,在这个闭环回路中,只要有一个元器件(或功能块)出故障,则往往整个回路中处处都存在故障现象。寻找故障的方法是先把反馈回路断开,使系统成为一个开环系统,然后再接入一适当的输入信号,利用信号寻迹法逐一寻找发生故障的元器件(或功能块)。以上就是电路测试的一些方法步骤,希望能给大家帮助。

    时间:2020-05-22 关键词: 电路 调试 故障解决

  • 嵌入式大牛的调试经验,值得你学习

    嵌入式大牛的调试经验,值得你学习

    你了解嵌入式吗?知道怎样调试吗?总有一些工程师吐槽嵌入式有多难学,Bug调试不知从何下手!今天小编就给大家分享一位嵌入式技术大牛的10年Bug调试经验心得!好好学习一下吧~笔者十年来做过小的嵌入式系统,大的电信系统以及基于web的系统。使用过C ++,Ruby,Java和Python等。这篇文章中的经验教训旨在帮助减少编码,测试和调试三个阶段的bug。 下面这些都是我经历过的会导致难点bug的问题: 1.事件顺序 在处理事件时,提出下列问题会很有成效:事件可以以不同的顺序到达吗?如果我们没有接收到此事件会怎么样?如果此事件接连发生两次会怎么样?哪怕通常不会发生,但系统(或交互系统)其他部分的bug可能会导致事件发生呢。 2.过早 这是第一点“事件顺序”的一个特例,但它确实会引起一些棘手的bug,因此我把它单独拎出来说明。例如,如果信令消息在配置和启动程序完成之前就被过早接收,那么可能就会有很多奇怪的行为发生。另一个例子:连接在被放进空闲列表之前就被标记为down。在调试这类问题时,我们总是假定在空闲列表中的时候连接被设置为down(但当时为什么不把它放到列表外面呢?)。这是我们思考的不足,没有考虑到有时候事情会过早发生。 3.悄无声息的故障 一些最难跟踪的bug有部分是由那些静静失败并扩展而不是抛出错误的代码所导致的。例如,没有检查代码却返回错误的系统调用(如bind)。又如:解析代码在它遇到错误元素的时候只是返回而非抛出错误。在错误状态中持续了一段时间的调用,会使调试变得更难。最好一旦检测到故障就返回错误。 4.If 有若干条件的if语句,if (a 或 b) ,特别是当有链接的时候, if (x) else if (y),都给我引发了很多bug。即使if语句在概念上很简单,但当有多个条件要跟踪的时候依然很容易出错。这些天,我尝试重写代码使之更简单,以避免处理复杂的if语句。 5.Else 有一些bug是因为没有正确考虑到如果条件为false时会发生什么而引起的。几乎在所有的情况下,都应该有一个else部分来应对每一条if语句。此外,如果你在if语句的分支中设置变量,那么或许你在另一个分支中也要设置。与此种情况相关的是标记被设置的情况。只添加用于设置的标记的条件不难,但是很容易忘了添加当标记应该再次重置时的条件。留下一个永远设置的标志可能会导致之后接连不断的bug。 6.改变假设 许多一开始最难预防的bug是因为改变了假设所造成的。例如,在开始时,可能每天只有一个客户事件。于是很多代码是在这样的假设下写下的。但是后来,设计改变了,允许每天有多个客户事件了。发生这种情况时,很难改变新设计影响到的所有情况。找到关于改变的所有显式依赖关系不难,难的是要找到所有隐性依赖于旧的设计的情况。例如,可能会有获取给定某一天所有客户事件的代码。其中的隐含假设是结果集永远不会超过客户的数量。关于这方面的问题我也没有很好的策略方法,如果各位有的话,还请不吝赐教。 7.日志记录 可视化程序做什么至关重要,特别是当逻辑很复杂的时候。确保补充足够多的(但不要太多)日志记录,这样你就可以说明为什么程序要这么做。如果一切正常,那也没关系,但要是有问题发生,你会很庆幸自己添加了这些日志。 测试 作为一个开发人员,直到要测试了我才会去处理功能。至少,这意味着每一行新的或改变了的代码行至少已经被执行过一次。此外,单元测试和功能测试都很不错,但还不够。新的功能也必须进行测试,并在类似于产品的环境中探索。只有这样,我才能说我完成了一个功能。下面是我经历过的bug所教会我的关于测试的一些重要的经验教训: 1.零和null 如果可行的话,确保总是用零和null来测试。对于字符串,这意味着要测试长度为零的字符串以及字符串为null两种情况。又如:测试TCP连接的断开,要在发送数据给它发送之前。不使用这些组合方法测试是导致bug出现的首位原因。 2.添加和删除 通常,新的功能包括能够添加新的配置到系统中——例如,一个用于手机号码转换的新的配置文件。测试它能否添加新的配置文件是很自然的。但是,我发现我们很容易忘记去测试删除配置文件是不是同样ok。 3.错误处理 处理错误的代码往往是难以测试的。最好有能检查错误处理代码的自动测试,但有时这是不可能的。我有时会使用的一招是临时修改代码,使得错误处理代码运行起来。要做到这一点最简单的方法是反转if语句——例如,从if error_count > 0改成error_count == 0。另一个例子是拼错数据库列名,从而导致期望的错误处理代码运行。 4.随机输入 通常,揭露bug测试的一种测试方法是使用随机输入。例如,H.323协议的ASN.1解码使用二进制数据操作。通过发送随机字节去解码,我们发现了解码器中的几个bug。另一个例子是用测试呼叫来生成脚本,此时呼叫持续时间,接听延迟,第一方挂断等等都是随机生成的。这些测试脚本会暴露许多bug,特别是一起发生的事件会产生并拢干扰。 5.检查不应该发生的动作 通常测试包括检查期望动作是不是发生了。但我们很容易忽视相反的情况——忘记检查不应该发生的动作是不是的确没有发生。 6.拥有工具 我创建了自己的小工具,以使得测试更加简单。例如,当我用VoIP SIP协议工作时,我写了一个能够用正是我想要的标题和值回复的小脚本。这个工具使得测试很多边界情况变得容易起来。另一个例子是可以进行API调用的一个命令行工具。通过启动逐渐添加所需小功能,我得到了一些非常有用的工具。自己写工具的好处是,我得到的正是我想要的。 在测试中发现所有的bug,那绝对是不可能的。有一个案例中,我更改了数字相关性的处理,数字由两个部分组成:路由地址前缀(通常是不变的),以及从000到999动态分配的数字。问题在于当找到相关性时,动态分配的数字的第一个数字会在呈现在表格中之前遭到误删。也就是说637变成了37。这意味着,到100之前它都是可以工作的,因此,前面100个电话是正常的,但是接下来的900个都是失败。所以,除非我在重新启动之前能够测试超过100次(事实是我没有),否则我在测试时就不会发现这个问题。 调试 1.讨论 帮助我最多的调试技术是与同事讨论问题。通常情况下,只是和同事说明问题,就会让我意识到问题的症结。此外,即使他们不是很熟悉有问题的代码,他们也往往能提出一些好点子。与同事讨论在处理最难的bug时特别有效。 2.密切关注 通常,如果调试问题花了很长时间,往往是因为我做了错误的假设。例如,我认为问题发生在某一方法中,但事实却是它甚至从来没有到达那个方法。或者,被抛出的异常不是我以为的那个。或者,我认为软件的最新版本上正在运行,但其实是一个旧版本。因此,一定要核实细节,而不是假设。人们更容易看到自己希望看到的东西,而不是事实。 3.最近的变化 当曾经可以正常工作的东西停止工作,那么这通常是因为最近改变的东西所导致的。在一个案例中,最近的改变只是日志记录,但是日志中的错误却导致了一个更大的问题。为了更容易找到这种回归,承认不同的提交会导致不同的变化,以及清楚说明这些更改会有所裨益。 4.相信用户 有时,当用户报告问题的时候,我的本能反应是,“这是不可能的。一定是他们做错了什么事”。但我学会了不再用这种方式去回应。更多的时间,事实往往证明,他们所报告的的确是实际发生的情况。因此,这些天,我开始接受他们所报告的内容的表明价值。当然,我依然会仔细检查一切是否被正确地设置等等。我见过很多这样的情况,让我明白,因为不寻常的配置或意料之外的用法而导致不可思议的事情的发生,而我默认的假设是,他们是正确的,程序是错误的。 5.测试修复 如果bug修复已准备就绪,那就必须进行测试。首先在修复前运行代码,并观察该bug。然后应用修复并重复测试案例。到此为止错误行为应消失。遵循这些步骤可以确保它确实是一个bug,并且此次修复的确可以解决这个问题。简单而有必要。 其他观察结果 现在工作于C++时所遇到的几类bug已经完全消失,像堆栈溢出,内存损坏,字符串问题和某种形式的内存泄漏。 其他问题,如循环错误和边界情况,我看到的要少得多。但是,这并不意味着那里没有bug。如果大家有什么有用的预防和发现bug的技术方法,欢迎留言。 作为过来人,最后还想说几句心灵鸡汤: 1、分享第一条经验:“学历代表过去、能力代表现在、学习力代表未来。” 2、一定要确定自己的发展方向,并为此目的制定可行的计划。 3、软件开发团队中,技术不是万能的,但没有技术是万万不能的! 4、详细制定自己软件开发专业知识学习计划,并注意及时修正和调整(软件开发技术变化实在太快)。 5、书籍是人类进步的阶梯,对软件开发人员尤其如此。 6、不要仅局限于对某项技术的表面使用上,哪怕你只是偶尔用一、二次。 7、在一种语言上编程,但别为其束缚了思想。“代码大全”中说:“深入一门语言编程,不要浮于表面”。 8、养成总结与反思的习惯,并有意识地提炼日常工作成果,形成自己的个人源码库、解决某类问题的通用系统体系结构、甚至进化为框架。 9、理论与实践并重,内外双修。 10、心态有多开放,视野就有多开阔。 11、尽量参加开源项目的开发、或者与朋友共同研制一些自己的产品,千万不要因为没有钱赚而不做。 12、书到用时方恨少,不要将自己的知识面仅仅局限于技术方面。 13、总结与反思: (a)不要去做技术上的高手,除非你的目标如此。虽然文章是关于提高软件开发知识的,做技术的高手是我一向都不赞同的。你可以提高自己的专业知识,但能胜任工作即止。 (b)提高软件知识和技术只是问题的表面,本质是要提高自己认识问题、分析问题、解决问题的思想高度。软件专业知识的很多方法和原理,可以很容易地延伸、应用到生活的其它方面。 (c)在能胜任工作的基础上,立即去涉猎其它领域的专业知识,丰富自己的知识体系、提高自己的综合素质,尤其是那些目标不在技术方面的朋友。以上就是嵌入式调试的方法,希望能给大家帮助。

    时间:2020-05-14 关键词: 嵌入式 调试 bug

  • 特斯拉上海超级工厂竣工 A阶段完成整车四大车间

    特斯拉上海超级工厂竣工 A阶段完成整车四大车间

    10月17日,工信部公布《道路机动车辆生产企业及产品公告》(第325批)拟发布的新增车辆生产企业及已准入企业变更信息名单,其中特斯拉在列。从上海市建设项目环评信息网站获悉,特斯拉上海超级工厂(一期)第一阶段已于9月11日竣工,并于10月15日进入调试阶段。 按照最初的计划,特斯拉上海超级工厂(一期)第一阶段的施工将分A、B两阶段实施,A阶段完成整车四大车间——冲压车间、车身车间、涂装车间、总装车间及配套工程的建设,计划于今年9月完成;B阶段将完成座椅生产区域、动力系统车间、电机车间的建设,预计于明年3月完成。 特斯拉上海超级工厂是上海有史以来最大的外资制造业项目,于今年1月7日正式破土动工。该项目将分两期实施,项目总投资140亿元,一期建成后年产15万辆纯电动整车,生产车型为Model 3,未来还将生产新车型Model Y。此前特斯拉CEO埃隆·马斯克表示,预计在今年年底前上海超级工厂将实现每周生产1000至2000辆Model 3。 虽然生产工艺和设备有变,但环评报告称,除不生产电机、座椅,动力系统中的外壳和集电器外,最终上海超级工厂(一期)的生产品和产量不发生变化。 在最新的环评信息中,记者留意到上海超级工厂在建设过程中出现部分生产工艺变动,包括取消B阶段的电机、座椅以及动力系统中的集电器和外壳的生产,冲压车间取消底围壳和顶盖的冲压制作,而涂装车间和动力车间分别拟设置电泳工艺实验室和动力系统实验室。

    时间:2019-10-18 关键词: 特斯拉 调试 上海工厂

  • 教你提升自己电路设计水平

    教你提升自己电路设计水平

    本技巧似乎显而易见,但往往被过分自信的人忽视,他们认为自己已经把要做的活都弄明白了。完全按照你的需要表述电路的方框图对电路的成功设计至关重要。在你开始工作之前,方框图为你提供了一个大纲,它还为将要查看和检查你电路的任何人提供了极好的参考资料。     图1:单张大幅原理图 2.各个击破 在很多情况下,在设计电路时你可能不会单打独斗,所以花时间将设计划分为各功能块,每个块都有定义的接口,就可以实现各个击破的策略;参与电路设计的设计师可以专注于各个块。这些块可以独立地用于你目前正着手的项目,也可以在将来重复用于不同的电路设计。通过这种方法,你可以在事情不顺利的时候轻松排除故障,因为你将能够识别你遇到的麻烦是哪个块引起的。     图2:清晰标记的框图 3.为电路网络命名 的确,对这一步可能会有疑惑,但确保对pcb上的每个网络进行命名并标注每个网络的用途,可在紧要关头,为你提供诸多帮助。当你必须调试或运行模拟时,它也很有用。网络命名可让你在出问题时,知道该在哪下手。请记住:使命名易于识别;使命名对其要传载的意义一目了然。 4.记笔记 谈到电子设计,你的笔记就是你的灵丹妙药。重要的是记录研发过程的每一步,你遇到的每个坑、找到的每个解决方案、以及与你的设计相关的任何其它内容。请务必记下为什么为你的设计选用某些组件、逻辑表的式样、以及设计电路时的任何特殊注意事项。你的笔记有多种用途: ? 通过清楚地记录每一步,你可以“回放”并查看哪里可能出问题、或你可在哪里进行修改以得到更高效的设计。 ? 可以使用和交叉引用以前项目的注释,以便更好地理解、实现更好的方案以及激发出与当前工作相关的更多灵感。 ? 你可以帮助其他人解决其设计问题,并在以后需要时阅读他们的笔记。 5.文本放置保持一致 如果你指定某些名称或在图表上进行注释,你会发现,再次查看时很难弄清这些文字到底是什么意思。在原理图上放置符号和名称时,请确保与命名过程保持一致。写注释时,不要在电路的一部分横着写,而在所有其它部分竖着写。尽量确保名称之间有一些空白,这样包括你在内的读者就不会感到困惑。注释间不要害怕有空白。实际上,空白有助于减少将图示与书写混在一起引发的混乱。这同样适用于速记命名。如果你要以缩写表述任何内容,请尝试在下面添加解释的“段子”,或确保它们易于识别。 6.流程化 不要削足适履试图将你的示意图(plan)和注释压缩进特定数量的页面。占页多少并不重要;不要苟且你原理图的质量。确保电路设计始终如一。这有助于提高可读性和更好的应用。在电子电路设计方面没有捷径;这完全取决于付出的努力和努力的结果。     图3:“流程化” 7.保留标题 为原理图的每页制作标题、进而提供了每页的更多信息,这会使你受益。除可读性更高外,这样做还可以更轻松地为你的原理图页编制索引。这在调试时会带来益处:当你需要引用电路的某个部分、但又太忙无暇翻遍每一页、只得救助大脑记忆试图找出所需图表的位置时——页索引会帮大忙。 8.使连接器可见 你需要能立即区分所有连接器。最好的选择是在原理图中使用引脚表述连接器。通过简单的连接器识别,你将能够正确地追溯电路,且不会迷失在连接中。选用引脚之所以方便,是因为它将“坚守”其位置。与贴纸(sticker)或颜色不同,引脚能更突出引人注目,而不会在图表和笔记中占用太多空间。

    时间:2019-09-08 关键词: 模拟 调试 电源资讯

  • GCC编译GDB调试程序

    GCC编译器能将C.C++语言源程序,汇编程序编译,链接为可执行的文件 hello.c #include int main(void) { printf("Hello World!n"); return 0; } 一:分四个阶段编译 预处理: gcc   -E  hello.c  -o hello.i 编译: gcc  -S hello.i  -o hello.S 汇编: gcc  -c  hello.S  -o  hello.o 链接: gcc  hello.o  -o  hello 二:单步完成编译 gcc  hello.c  -o  hello 三:运行 ./hello      输出: Hello World!  编译选项: -c  只是编译不连接,生成目标文件“.o” -S 只是编译不汇编,生成汇编代码 -E 只进行预编译,不做其他处理 -g  在可执行程序中包含标准调试信息(用于GDB调试) -o file  指定输出文件为file -v  打印出编译器内部编译各过程的命令行信息和编译器的版本 -static  链接静态库 -l dir  在头文件的搜索路径列表中添加dir 路径     eg: gcc  -l   /home/student/include   test.c  -o  test -L  在库文件的搜索路径列表中添加dir路径 -lname 链接名为libname.so的库文件    eg:gcc  -L /home/student/lib  -lmylib  test.c  -o  test 警告和出错选项 -ansi  输出符合ANSI  C标准语法的警告信息 -pedantic  允许ANSI  C变准所列的全部警告信息 -Wall  允许发出GCC提供的所有有用的警告信息 -w  关闭所有的警告信息 -Werror   把所有的警告信息转化为错误信息,并在警告发出时终止编译过程 GDB 是GNU开源组织发布的一个强大的Linux下的程序调试工具,基于命令行的工作模式,主要用来调试C和C++程序 ,通过GDB能在程序运行时动态观察程序的内部结构,变量值和内存的使用情况。 使用流程: 查看文件-》设置断点-》查看断点情况-》运行代码-》查看变量值-》单步运行-》恢复程序运行 一:GDB中源代码查看命令 list  /l  行号或函数名            //查看指定位置代码 list   //显示程序第linenum行的周围的源程序 list  //显示函数名为function的函数的源程序 list    //  显示当前行后面的源程序 list   //显示哪个文件中的哪个函数的源程序 eg: list  src/fun1.c:fun1 list   //哪个文件的哪一行周围的源程序 eg:list  src/fun1.c:1   二:运行代码 运行代码:rum  /r 三:设置断点与恢复命令 info b  break  /b    行号或函数名 delete  断点号 disable  断点号 enable  断点号 step  /s  单步调试(进入子函数) next  /n  单步调试(不进入子函数) continue  /c  继续执行函数,知道函数结束或遇到新的断点 四:查看运行数据命令 print  /p  表达式或变量      //查看程序运行时对应表达式或变量的值 五:修改运行参数命令 set  variable  变量名=设定值

    时间:2019-09-02 关键词: 调试 gcc

  • GDB的一些命令使用

    GDB的一些命令使用 本文内容来自:linuxc编程一站式学习 在编译文件是加上 -g 编译选项即可调试。gdb调试和源文件有关,不止是和编译生成的文件有关。 wytx@ubuntu:~$ gcc -g -o hello hello.c wytx@ubuntu:~$ gdb ./hello 这就启动了gdb,下面是调试时需要用到的常用命令 单步、函数跟踪等基本命令 命令 描述 backtrace(或bt) 查看各级函数调用及参数 finish 执行到当前函数返回,然后停下来等待命令 frame(或f) 帧编号 选择栈帧 info(或i) locals 查看当前栈帧局部变量的值 list(或l) 列出源代码,接着上次的位置往下列,每次列10行 list 行号 列出从第几行开始的源代码 list 函数名 列出某个函数的源代码 next(或n) 执行下一行语句 print(或p) 打印表达式的值,通过表达式可以修改变量的值或者调用函数 set var 修改变量的值 start 开始执行程序,停在main函数第一行语句前面等待命令 step(或s) 执行下一行语句,如果有函数调用则进入到函数中 直接回车 执行上一条命令 断点相关的命令 命令 描述 break(或b) 行号 在某一行设置断点 break 函数名 在某个函数开头设置断点 break…if… 设置条件断点 continue(或c) 从当前位置开始连续而非单步执行程序 delete breakpoints 删除断点 display 变量名 跟踪查看一个变量,每次停下来都显示它的值 disable breakpoints 禁用断点 enable breakpoints 启用断点 info(或i) breakpoints 查看当前设置了哪些断点 run(或r) 从头开始连续而非单步执行程序 undisplay 取消对先前设置的那些变量的跟踪 break 10 if sum != 0 //在第10行设置断点,当sum不等于0是才有效 观察点相关命令 命令 描述 watch 变量名 设置观察点(例如 watch temp) info(或i)watchpoints 查看当前设置了哪些观察点 delete watchpoints 也是可以删除观察点的 x 例如:x/7b 从某个位置开始打印存储器的一段内容,全部当成字节来看,而不区分哪些字节属于哪些变量;x命令打印存储器中的内容。 7b是打印格式, b表示每个字节一组, 7表示打印7组

    时间:2019-08-26 关键词: 调试 gdb

  • 单链表操作

    /*************单链表的操作函数总结*****************/ #include#include#include#includeusing namespace std; struct STU{     char name[20];     char stuno[10];     int age;     int score; }stu[50]; typedef struct STU ElemType; struct LNODE{     ElemType data;     struct LNODE *next; }; typedef struct LNODE LNode; typedef struct LNODE *LinkList; /*比较两个链表元素的大小*/ int Less_EqualList(ElemType *e1,ElemType *e2) {     if(strcmp(e1->name,e2->name) next)     {         p = p->next;         printf("%-10s %st%dt%dn",p->data.name,p->data.stuno,p->data.age,p->data.score);     }     return 1; } /*节点初始化*/ int init(LinkList *L) {     //用malloc动态分配节点     *L = (LNode *)malloc(sizeof(LNode));     if(!L)     //若分配失败,返回         return 0;     //初始化数据域     memset(&((*L)->data),0,sizeof(struct STU));         //初始化指针域     (*L)->next = NULL;     return 1; } /*测试数据是否存在*/ int GetElem(LinkList L,int i,ElemType *e) {     LinkList p;     int j;          p = L->next;     j = 1;          while(p && jnext;         ++j;     }          if(!p || j>1)         return 0;          *e = p->data;     return 1; } /*向链表中插入数据*/ int ListInsert(LinkList L,int i,ElemType e) {     LinkList p,s;     int j;          p = L;     j = 0;          while(p && jnext;         ++j;     }          if(!p || j>i-1)         return 0;          s = (LinkList)malloc(sizeof(LNode));     s->data = e;          s->next = p->next;     p->next = s;     return 1; } /*从链表中删除数据*/ int ListDelete(LinkList L,int i) {     LinkList p;     int j;     p = L;     j = 0;     while(p && jnext;         ++j;     }     if(!p || j>i-1)         return 0;     p->next = p->next->next;     p->next->data = p->next->next->data;     return 1; } /*合并两个链表*/ void MergeList(LinkList La,LinkList Lb,LinkList *Lc) {     /*合并单链表La和Lb到Lc中*/     LinkList pa,pb,pc;     pa = La->next;     pb = Lb->next;     *Lc = pc = La;     while(pa && pb)     {         if(Less_EqualList(&pa->data,&pb->data))         {             pc->next = pa;             pc = pa;             pa = pa->next;         }         else         {             pc->next = pb;             pc = pb;             pb = pb->next;         }     }     pc->next = pa?pa:pb;     free(Lb); } int main(int argc, char *argv[]) {     QCoreApplication a(argc, argv);          struct STU e; //定义一个data     LinkList La,Lb,Lc;     printf("nn----------List Demo is running...----------nn");     printf("First is InsertList function.n");     init(&La);     strcpy(e.name,"stu1");     strcpy(e.stuno,"100001");     e.age = 80;     e.score = 1000;     ListInsert(La,1,e);     strcpy(e.name,"stu3");     strcpy(e.stuno,"100002");     e.age = 80;     e.score = 1000;     ListInsert(La,2,e);     printList(La);     getchar();     strcpy(e.name,"stu5");     strcpy(e.stuno,"100003");     e.age = 80;     e.score = 1000;     ListInsert(La,3,e);     printList(La);     getchar();     init(&Lb);     strcpy(e.name,"stu2");     strcpy(e.stuno,"100001");     e.age = 80;     e.score = 1000;     ListInsert(Lb,1,e);     strcpy(e.name,"stu4");     strcpy(e.stuno,"100002");     e.age = 80;     e.score = 1000;     ListInsert(Lb,2,e);     strcpy(e.name,"stu6");     strcpy(e.stuno,"100001");     e.age = 80;     e.score = 1000;     ListInsert(Lb,3,e);     printList(Lb);     getchar();     MergeList(La,Lb,&Lc);     printList(Lc);     getchar();     return a.exec(); }

    时间:2019-06-14 关键词: 调试 单链表

  • VS2015对WDK10驱动程序进行双机调试

    VS2015对WDK10驱动程序进行双机调试

    【1】设置Visual Studio 2015调试方式:主计算机:WIN7 64位 虚拟机:WIN7 64位 调试器:VS2015 调试的软件:内核驱动程序一、主计算机和虚拟机两台机器必须关闭防火墙,必须能够互相ping通(使用桥接模式).二、 将WDK10携带的调试驱动包拷贝到虚拟机中安装:1)WDK10安装时如果用的是默认路径:                          //两个都可以安装,因为VS2015可以调试32位和64位的驱动程序C:Program Files (x86)Windows Kits10Remotex64WDK Test Target Setup x64-x64_en-us     //64位调试驱动包C:Program Files (x86)Windows Kits10Remotex86WDK Test Target Setup x86-x86_en-us     //32位调试驱动包2)如果你自定义了WDK10安装路径,请到你指定的目录寻找.三、虚拟机添加串口:1)设置-->添加-->串型接口-->输出到命名管道.2)设置选项为“另一端为应用程序” 并且“ 为管道命名不要为常见名称”  --> 添加命名管道完成.问题:因为一般虚拟机的串口1是打印机,串口2才是我们创建的,所以可能连接时,会弄错,导致后来不能连接上串口通道.解决:打开“运行”输入MSConfig,弹出MSConfig工具:(原创百度经验地址:http://jingyan.baidu.com/article/3a2f7c2e6dee4126afd611c6.html)                     1)打开boot工具的debug,修改com1为com2:        四、虚拟机进入调试模式://使用管理员权限打开cmd,输入以下命令       1)bcdedit /debug ON                        开启调试模式       //设置串口的波特率为115200bps(其实默认就是,不用修改)       2)bcdedit /dbgsettings serial debugport:串口号 baudrate:115200       3)bcdedit /dbgsettings                      查看当前的调试配置       4)bcdedit /timeout 10                        选择菜单的超时,我设置为10秒五、驱动程序的项目点右键-->选择属性菜单-->选择调试选项-->在右边要启动的调试器上选择Debugging Tools for windows – Kernel Debugger-->在Remote Computer Name上点击配置,就会出现配置窗口,界面如下:1)点击Add New Devide添加调试主机.2)下一步3)点击下一步,会对虚拟机进行自动安装,在此过程中,不应动虚拟机:4)安装完成后,点击应用:5)在VS2015中选择调试-->附加到进程:     1、传输:选择Windows Kernel Mode Debugger     2、限定符:选择创建新测试设备时输入的那个名称     3、以下可用进程出现一个Kernel的进程,点击它附加.6)附加完成后,VS2015右下角会出现Debugger的“waiting to reconnect”.7)如果没有问题,重启虚拟机,VS2015右下角会出现Debugger就会连接上了,状态为“正在跑”.8)虚拟机启动完成后,打开“驱动程序加载工具"   必须确保将加载的驱动程序的.sys是DEBUG版的,而且要与VS2015调试中的代码对应.   (你的sys和加载驱动工具必须已经测试过能够加载驱动程序.)   //这就需要先看地址:http://blog.csdn.net/aaron133/article/details/78091639  加载驱动的文章.   9)打开“驱动程序加载工具"后,VS2015中点击暂停:,你会发现虚拟机整个卡住了.10)现在才能设置有效断点,F9设置好断点后:在VS2015右下角的Debugger界面中输入:kd> g        表示继续跑.11)使用加载驱动程序加载我们的.sys驱动程序,当sys跑起来后,就能够断下来了:

    时间:2019-06-14 关键词: 调试 wdk10

  • Linux基础,解决GCC常见错误

    Linux基础,解决GCC常见错误

    Gcc编译器如果发现源程序中有错误,就无法继续进行,也无法生成最终的可执行文件。为了便于修改,gcc给出错误资讯,我们必须对这些错误资讯逐个进行分析、处理,并修改相应的语言,才能保证源代码的正确编译连接。gcc给出的错误资讯一般可以分为四大类,下面我们分别讨论其产生的原因和对策。 1. 第一类∶C语法错误 错误资讯∶文件source.c中第n行有语法错误(syntex errror)。这种类型的错误,一般都是C语言的语法错误,应该仔细检查源代码文件中第n行及该行之前的程序,有时也需要对该文件所包含的头文件进行检查。有些情况下,一个很简单的语法错误,gcc会给出一大堆错误,我们最主要的是要保持清醒的头脑,不要被其吓倒,必要的时候再参考一下C语言的基本教材。 2. 第二类∶头文件错误 错误资讯∶找不到头文件head.h(Can not find include file head.h)。这类错误是源代码文件中的包含头文件有问题,可能的原因有头文件名错误、指定的头文件所在目录名错误等,也可能是错误地使用了双引号和尖括号。 3. 第三类∶档案库错误 错误资讯∶连接程序找不到所需的函数库,例如∶ ld: -lm: No such file or directory 这类错误是与目标文件相连接的函数库有错误,可能的原因是函数库名错误、指定的函数库所在目录名称错误等,检查的方法是使用find命令在可能的目录中寻找相应的函数库名,确定档案库及目录的名称并修改程序中及编译选项中的名称。 4. 第四类∶未定义符号 错误资讯∶有未定义的符号(Undefined symbol)。这类错误是在连接过程中出现的,可能有两种原因∶一是使用者自己定义的函数或者全局变量所在源代码文件,没有被编译、连接,或者干脆还没有定义,这需要使用者根据实际情况修改源程序,给出全局变量或者函数的定义体;二是未定义的符号是一个标准的库函数,在源程序中使用了该库函数,而连接过程中还没有给定相应的函数库的名称,或者是该档案库的目录名称有问题,这时需要使用档案库维护命令ar检查我们需要的库函数到底位于哪一个函数库中,确定之后,修改gcc连接选项中的-l和-L项。  排除编译、连接过程中的错误,应该说这只是程序设计中最简单、最基本的一个步骤,可以说只是开了个头。这个过程中的错误,只是我们在使用C语言描述一个算法中所产生的错误,是比较容易排除的。我们写一个程序,到编译、连接通过为止,应该说刚刚开始,程序在运行过程中所出现的问题,是算法设计有问题,说得更玄点是对问题的认识和理解不够,还需要更加深入地测试、调试和修改。一个程序,稍为复杂的程序,往往要经过多次的编译、连接和测试、修改。下面我们学习的程序维护、调试工具和版本维护就是在程序调试、测试过程中使用的,用来解决调测阶段所出现的问题。

    时间:2019-05-26 关键词: Linux 调试 gcc

  • 单片机调试出现一些不常见问题及原因

    1、4位共阳数码管的有一个位的其中一段不亮,而其他位的该段能正常显示。这有些不符合常理,因为共阳数码管的4个为的段是连在一起的,如果是程序问题或者硬件连接有问题,应该4位全不亮。 原因:经排查,原因是发现电路板的背面该段和其他位的位选线短路了,这样就导致当动态扫描的时候,要显示这一位的时候,其他三个位选是拉低的,这样就造成了这一段应该为高电平被拉低了,所以出现了这种四个位中只有一位的段显示不正常。 2、数码管显示出现了严重的重影,程序没有问题的(在其他板子上测试没有问题)。 原因:经排查,排除了器件的问题,也排查了连线问题。最后发现了共阳端的驱动三极管的基极的电压和正常的有些不一样,但是差别很小。我发现为了保护单片机的引脚,给单片机多加了一层底座,怀疑底座的原因造成。直接拆掉一层底座,发现数码管显示正常了。所以应该是底座的电阻加上限流电阻之后阻值过大,导致单片机输出电流过小,无法驱动pnp三极管输出低电平。造成数码管有严重残影。

    时间:2019-05-22 关键词: 单片机 调试 常见问题

  • flash接口电路的实现

    flash接口电路的实现

    0引言 我们在进行嵌入式系统设计的过程中,根据需求,要设计出特定的嵌入式应用系统,而嵌入式应用系统的设计包含硬件系统设计和软件系统设计两个部分,并且这两部分设计是互相关联、密不可分的,嵌入式应用系统的设计经常需要在硬件和软件设计之间进行权衡与折中。因此,这就要求嵌入式系统设计者具有较深厚的硬件和软件基础,并具有熟练应用的能力。在整个设计过程中,硬件设计是系统设计的基础和核心,而各功能部件在整个设计中的调试又是该环节的重点和难点。本文详细介绍嵌入式系统Flash存储器的接口电路的调试。 1 Flash存储器接口电路的引脚信号及各项特性 1.1 Flash存储器接口电路的特点 Flash存储器是一种可在系统(In-System)中进行电擦写,掉电后信息不会丢失的存储器。它具有低功耗、大容量、擦写速度快、可整片或分扇区在系统编程(烧写)、擦除等特点,并且可由内部嵌入算法完成对芯片的操作,因而在各种嵌入式系统中得到了广泛的应用。作为一种非易失性存储器,Flash在系统中通常用于存放程序代码、常量表以及一些在系统掉电后需要保存的用户数据等。常用的Flash为8位或16位数据宽度,编程电压为单3.3V。主要有ATMEL、AMD、HYUNDAI等生产厂商,他们生产的同型器件一般具有相同的电气特性和封装形式,可通用。 1.2以HY57V641620为例的SDRAM接口电路的基本特性 本文以Flash存储器HY29LV160为例,简要描述一下Flash存储器的基本特性: HY29LV160的单片存储容量为16M位(2M字节),工作电压为2.7V~3.6V,采用48脚TSOP封装或48脚FBGA封装,16位数据宽度,可以以8位(字节模式)或16位(字模式)数据宽度的方式工作。 HY29LV160仅需单3V电压即可完成在系统的编程与擦除操作,通过对其内部的命令寄存器写入标准的命令序列,可对Flash进行编程(烧写)、整片擦除、按扇区擦除以及其它操作。 HY29LV160的逻辑框图、引脚分布及信号描述分别如图1和表1所示: 图1 HY29LV160引脚分布(TSOP48封装) 表1 HY29LV160的引脚信号描述引 脚类型描 述A[19:0]I地址总线。在字节模式下,DQ[15]/A[-1]用作21位字节地址的最低位。DQ[15]/A[-1]DQ[14:0]I/O三态数据总线。在读写操作时提供8位或16位数据的宽度。在字节模式下,DQ[15]/A[-1]用作21位字节地址的最低位,而DQ[14:8]处于高阻状态。BYTE#I模式选择。低电平选择字节模式,高电平选择字模式CE#I片选信号,低电平有效。在对HY29LV160进行读写操作时,该引脚必须为低电平,当为高电平时,芯片处于高阻旁路状态OE#I输出使能低电平有效输出使能,低电平有效。在读操作时有效,写操作时无效。WE#I低电平有效写使能,低电平有效。在对HY29LV160进行编程和擦除操作时,控制相应的写命令。RESET#I硬件复位,低电平有效。对HY29LV160进行硬件复位。当复位时,HY29LV160立即终止正在进行的操作。RY/BY#O用就绪/忙 状态指示。用于指示写或擦除操作是否完成。当HY29LV160正在进行编程或擦除操作时,该引脚位低电平,操作完成时为高电平,此时可读取内部的数据。VCC--3.3V电源VSS--接地1.3 以HY29LV160为例的Flash接口电路的使用方法下面,我们使用HY29LV160来构建存储系统。由于ARM微处理器的体系结构支持8位/16位/32位的存储器系统,对应的可以构建8位、16位、32位的Flash存储器系统。32位的存储器系统具有较高的性能,而16位的存储器系统则在成本及功耗方面占有优势,而8位的存储器系统现在已经很少使用。下面主要介绍16位和32位的Flash存储器系统的构建。 1.3.1.16位的FLASH存储器系统 在大多数的系统中,选用一片16位的Flash存储器芯片(常见单片容量有1 MB 、2MB 、4MB 、8MB 等)构建16位Flash的存储系统已经足够,在此采用一片HY29LV160构建16位的Flash存储器系统,其存储容量为2MB。Flash存储器在系统中通常用于存放程序代码,系统上电或复位后从此处获取指令并开始执行,因此,应将存有程序代码的Flash存储器配置到ROM/SRAM/FLASH Bank0,即将S3C4510B的nRCS<0>(Pin75)接至HY29LV160的CE#端。 HY29LV160的RESET#端接系统复位信号; OE#端接S3C4510B的nOE(Pin72); WE#端S3C4510B的nWBE<0>(Pin100); BYTE#上拉,使HY29LV160工作在字模式(16位数据宽度); RY/BY#指示HY29LV160编程或擦除操作的工作状态,但其工作状态也可通过查询片内的相关寄存器来判断,因此可将该引脚悬空; 地址总线[A19~A0]与S3C4510B的地址总线[ADDR19~ADDR0]相连; 16位数据总线[DQ15~DQ0]与S3C4510B的低16位数据总线[XDATA15~XDATA0]相连。 注意此时应将S3C4510B的B0SIZE[1:0]置为“10”,选择ROM/SRAM/FLASH Bank0为16位工作方式。 1.3.2. 32位的FLASH存储器系统 作为一款32位的微处理器,为充分发挥S3C4510B的32性能优势,有的系统也采用两片16位数据宽度的Flash存储器芯片并联(或一片32位数据宽度的Flash存储器芯片)构建32位的Flash存储系统。其构建方式与16位的Flash存储器系统相似。 采用两片HY29LV16并联的方式构建32位的FLASH存储器系统,其中一片为高16位,另一片为低16位,将两片HY29LV16作为一个整体配置到ROM/SRAM/FLASH Bank0,即将S3C4510B的nRCS<0>(Pin75)接至两片HY29LV16的CE#端; 两片HY29LV160的RESET#端接系统复位信号; 两片HY29LV160的OE#端接S3C4510B的nOE(Pin72); 低16位片的WE#端接S3C4510B的nWBE<0>(Pin100),高16位片的WE#端接S3C4510B的nWBE<2>(Pin102); 两片HY29LV160的BYTE#均上拉,使之均工作在字模式; 两片HY29LV160的地址总线[A19~A0]均与S3C4510B的地址总线[ADDR19~ADDR0]相连; 低16位片的数据总线与S3C4510B的低16位数据总线[XDATA15~XDATA0]相连,高16位片的数据总线与S3C4510B的高16位数据总线[XDATA31~XDATA16]相连。 注意此时应将S3C4510B的B0SIZE[1:0]置为“11”,选择ROM/SRAM/FLASH Bank0为32位工作方式。 2.S3C4510B系统管理器关于存储器映射的工作原理 当系统设计制作完成时,必须经过仔细的调试,才能保证系统按照设计意图正常工作。尽管系统的调试与个人对电路工作原理的理解和实际的电路调试经验有很大的关系,但一定的调试方法也是必不可少的。掌握正确的调试方法可使调试工作变得容易,大大缩短系统的开发时间,反之,可能会使整个系统的开发前功尽弃,以失败告终。 在系统的两类存储器中,SDRAM相对于FLASH存储器控制信号较多,似乎调试应该困难一些,但由于SDRAM的所有刷新及控制信号均由S3C4510B片内的专门部件控制,无需用户干预,在S3C4510B正常工作的前提下,只要连线无误,SDRAM就应能正常工作,反之,Flash存储器的编程、擦除操作均需要用户编程控制,且程序还应在SDRAM中运行,因此,应先调试好SDRAM存储器系统,再进行Flash存储器系统的调试。 基于S3C4510B系统的最大可寻址空间为64MB,采用统一编址的方式,将系统的SDRAM、SRAM、ROM、Flash、外部I/O以及片内的特殊功能寄存器和8K一体化SRAM均映射到该地址空间。为便于使用与管理,S3C4510B又将64MB的地址空间分为若干个组,分别由相应的特殊功能寄存器进行控制: (1) ROM/SRAM/Flash组0~ROM/SRAM/Flash组5,用于配置ROM、SRAM或Flash,分别由特殊功能寄存器ROMCON0~ROMCON5控制; (2)DRAM/SDRAM组0~DRAM/SDRAM组3用于配置DRAM或SDRAM,分别由特殊功能寄存器DRAMCON0~DRAMCON3控制; (3)外部I/O组0~外部I/O组3用于配置系统的其他外扩接口器件,由特殊功能寄存器REFEXTCON控制; (4)特殊功能寄存器组用于配置S3C4510B片内特殊功能寄存器的基地址以及片内的8K一体化SRAM,由特殊功能寄存器SYSCFG控制; 在系统中,使用了Flash存储器和SDRAM,分别配置在ROM/SRAM/FLASH组0和DRAM/SDRAM组0,暂未使用外扩接口器件。 3基于S3C4510B的嵌入式系统Flash存储器接口电路的调试 Flash存储器的调试主要包括Flash存储器的编程(烧写)和擦除,与一般的存储器件不同,用户只需对Flash存储器发出相应的命令序列,Flash 存储器通过内部嵌入的算法即可完成对芯片的操作,由于不同厂商的Flash存储器在操作命令上可能会有一些细微的差别,Flash存储器的编程与擦除工具一般不具有通用性,这也是为什么Flash接口电路相对较难调试的原因之一,因此,应在理解Flash存储器编程和擦除的工作原理的情况下,根据不同型号器件对应的命令集,编写相应的程序对其进行操作。 若使用SDT调试环境,调试过程与上述步骤相似。 >obey C:memmap.txt 打开AXD Debugger的命令行窗口,执行obey命令: 此时,2MB的Flash存储器映射到地址空间的0x0000,0000~0x001F,FFFF处,选择菜单Processor Views→Memory选项,出现存储器窗口,在存储器起始地址栏输入Flash存储器的映射起始地址:0x0,数据区应显示Flash存储器中的内容,若Flash存储器为空,所显示的内容应全为0xFF,否则应为已有的编程数据。双击其中的任一数据,输入新的值,对应存储单元的内容应不能被修改,此时可初步认定Flash存储器已能被访问,但是否能对其进行正确的编程与擦除操作,还需要编程验证,通过程序对Flash存储器进行编程和擦除操作。 4结束语 这样整个基于的嵌入式系统Flash存储器接口电路的调试基本上完成了,当然对于不同的系统,操作是略有不同的,我们可以根据所要开发或使用的嵌入式系统模式,进行适当的调整,保证我们正确的使用Flash存储器。

    时间:2018-11-19 关键词: 嵌入式系统 调试 电源技术解析 flash存储器

  • 裸机调试分享:RVDS4.0 + openJTAG

    上个月买了一个openJTAG一直没时间使用,今天用了一下,还行,给大家分享一下RVDS4.0与openJTAG的使用方法首先得安装好openJTAG的相关驱动以及GDB调试软件,这个在openJTAG的使用手册上面都有,这里就不多说了,来看看RVDS4.0的设置吧只有一个.s文件,是汇编写的,用来测试无uboot环境下的启动的,其它编译设置请看我的博文,RVDS4.0建立工程,我这里使用的地址为0x0,地址,也就是ARM启动后第一条指令所在位置.;----------------------------------------------------------------------------------------------------- ;功能: S3C6410硬件初始化代码 ;作者: 异灵元(cp1300@139.com) ;创建时间:2012-10-27 ;修改时间:2012-10-27 ;修订说明: ;----------------------------------------------------------------------------------------------------- PRESERVE8 INCLUDE     s3c6410_map.inc ;寄存器地址映射 AREA    Init,CODE,READONLY ENTRY  B ResetHandler ;系统硬件复位 B UndHandler ;未定义指定中断 B SWIHandler       ;软件中断 B PaAbort             ;取指令异常中断 B DaAbort            ;取数据异常中断  B . ;保留 B IRQHandler      ;中断 B FIQHandler      ;快速中断 ResetHandler PROC ;----------------------------------------------------------------------------------------------------- ;关闭看门狗 ;----------------------------------------------------------------------------------------------------- LDR R0, =S3C6410_WTCON ;看门狗寄存器地址 LDR R1, =0x0 STR R1, [R0] ;写0,关闭看门狗 ;----------------------------------------------------------------------------------------------------- ;点亮所有LED ;----------------------------------------------------------------------------------------------------- LDR R0, =S3C6410_GPMCON LDR R1, =0x1111 ;推挽输出 STR R1, [R0] LDR R0, =S3C6410_GPMDAT LDR R1, =0x0 ;写入0,点亮所有灯 STR R1, [R0] main_loop B main_loop ENDP UndHandler PROC EXPORT UndHandler [WEAK] B . ENDP SWIHandler PROC EXPORT SWIHandler [WEAK] B . ENDP PaAbort PROC EXPORT PaAbort [WEAK] B . ENDP DaAbort PROC EXPORT DaAbort [WEAK] B . ENDP IRQHandler PROC EXPORT IRQHandler [WEAK] B . ENDP FIQHandler PROC EXPORT FIQHandler [WEAK] B . ENDP END再看看如何配置调试(默认大家已经安装好了openJTAG相关驱动) 1.首先得安装RVDS4.0,不会的看看我的博客安装RVDS4.0 : http://blog.csdn.net/cp1300/article/details/7772645RVDS4.0建立工程: http://blog.csdn.net/cp1300/article/details/7772809 2.安装zylincdt插件.不好意思我的是汉语的,大家看着办啊点击‘帮助’ -------------- ‘SoftwareUpdates’ ---------------‘Find and Install’点开后选择下面的一个选项,下一步如下图界面点击新建远程站点 ,右边的第一个 名称填写:  zylincdtURL填写:         http://opensource.zylin.com/zylincdt  勾选后点击完成,需要联网下载更新,按提示安装,中途可能会有警告,确认就行,安装完成后会自动重启RVDS的,完成后在调试里面会多出zylin 相关的调试选项.3.新建一个调试在 Zylin Embedded debug(Native) 下面新建一个调试配置,如上图,我的是 ok6410无Uboot调试在Debugger选项卡上面需要注意了Debugger 选择 Embedded GDB,设置如上图所示勾选一个 默认的断点,我的是ResetHandler这个按照自己的实际情况,如果有C语言这里一般就是main函数了GDB调试器:选择你的openJLINK光盘里面安装的工具.说明里面都有,我的路径是:D:Program Filesyagartobinarm-elf-gdb.exeGDB命令文件这个也是光盘里面带的,我的是:D:DesktopOK6410ok6410filestarts3c6410_gdb.init在命令选项卡里面添加四条命令,功能依次是 载入调试文件,设置断点,继续执行命令为monitor resetmonitor haltload//break maincontinue这样可以一键运行,将//去掉程序会自动停在主函数,注意下一次仿真下载之前需要停止本次仿真.应用即可4.开始调试在openJTAG的终端里面输入 halt,暂停,其实可以在设置的时候第一条指令如果是break,这个步骤就可以省略了,但是建议多次调试后复位一下开发板调试前一定要先打开OPENJTAG : OPENOCD GUI,如图设置在光盘手册里面也有.编译好工程后点击调试即可注意要选择刚刚建立的调试配置.5.调试出现如上图,就成功了,省下的就非常简单了,大家自己琢磨琢磨.看完后大家肯定会觉得没什么用,因为自己手上可能没有openJTAG,并且这个还有点贵,但是告诉大家一个好消息,JLINK一样可以这样用,一样可以再RVDS4.0上面进行调试,使用方法和eclipse一模一样的,不懂可以查eclipse的使用,但是jlink很容易卡死,很不稳定。一样的程序,跑飞了。。。卡死了。。。附上:jlink调试,大部分操作都一样,设置如下,调试前想打开jlink-gdb

    时间:2018-11-15 关键词: 调试 裸机 openjtag

  • 台达变频器在数控机床的应用

    台达变频器在数控机床的应用

    一、简介 数控机床的技术水平高低及其在金属切削加工机床产量和总拥有量的百分比,是衡量一个国家国民经济发展和工业制造整体水平的重要标志之一。数控车床是数控机床的主要品种之一,它在数控机床中占有非常重要的位置,几十年来一直受到世界各国的普遍重视,并得到了迅速的发展。主轴是车床构成中一个重要的部分,对于提高加工效率,扩大加工材料范围,提升加工质量都有着很重要的作用。经济型数控车床大多数是不能自动变速的,需要变速时,只能把机床停止,然后手动变速。而全功能数控车床的主传动系统大多采用无级变速。目前,无级变速系统主要有变频主轴系统和伺服主轴系统两种,一般采用直流或交流主轴电机。通过带传动带动主轴旋转,或通过带传动和主轴箱内的减速齿轮(以获得更大的转矩)带动主轴旋转。由于主轴电机调速范围广,又可无级调速,使得主轴箱的结构大为简化。目前对客户来说由于变频器的高性价比,所以变频器在车床上使用非常普遍。台达M系列变频器以其独特的性能和优越的性价比,在数控机床的应用上迅速崛起,成为目前市场上一支强大的生力军。 二、变频器特点的介绍 1.体积小,属于迷你型产品,占用控制柜空间较小; 2.控制方式为正弦波SPWM(提供无速度反馈矢量控制),控制性能较以前的VF控制方式有很大性能上的改善,特别是在低速转矩上满足机床主轴的需求,5HZ时起动转矩能够达到150%以上; 3.载波频率范围0-15KHz,减小电机的电磁噪音; 4.提供标准的0-10V模拟量接口(输入阻抗47Kohm,输出阻抗250Kohm),能够与大多数数控系统接口兼容,通用性强; 5.过负载能力强,150%以上额定输出电流超过一分钟; 6.提供多功能的输出端子信号,例如零速信号,运转中信号,速度到达信号,故障指示,满足系统对于主轴速度状态的监控; 7.自动转矩补偿,满足机床主轴在低速情况下的加工需求; 8.提供三组异常纪录,供维修人员从侧面了解机床主轴实际的运行状况; 9.电机参数自动整定功能,在线识别电机参数,保证系统的稳定性和精确性。 三、调试环境以及接线、调试方法客户选配电机为3.0KW/50Hz/380V,选用变频器型号为VFD037M43,制动电阻400W/150ohm。 变频器AVI/GND端子提供与数控系统速度模拟量,AVI接数控系统模拟量接口正信号,GND接负信号,信号为0-10V模拟电压信号,控制主轴转速。M0/M1/GND为变频器的正转/反转信号端子,通常由数控系统发出正转信号FWD或者反转REV,来驱动中间继电器,中间继电器的常开接点接入变频器M0/GND或者M1/GND,从而控制变频器的正反转。 在参数调整过程中,需要注意: 1.P00参数为选择主频率输入设定来源,设置为模拟信号0-10V输入(1); 2.P01参数为运转信号来源设定,设置为外部端子信号控制(2); 3.P03最高操作频率选择,对应于模拟信号10V输入时变频器的输出频率,由于是在0-3500rpm范围内调速,将机械减速比这算进去以后,此参数需要设置为184HZ; 4.P04和P05按照电机铭牌设置,P04=50Hz,P05=380V; 5.P10和P11为加速时间和减速时间,根据客户的要求,P10=5S,P11=5S; 6.P105为控制方式的选择,需要选择矢量控制,P105=1; 特别需要注意,由于矢量控制需要提供电机参数(阻抗),变频器提供电机参数自整定功能P103,选择P103=2,通过面板运行键,变频器会自动运行。自动运行过程中,除了计算出电机参数以外,还能够检测出空载电流,这几个参数对于矢量控制能够表现出较高的性能非常重要,这个过程会持续十几秒钟时间。在执行自整定功能前,一定要确认电机侧是否没有任何连接,包括减速皮带。 四、调试结果 测试结果如下: 表1 空载电流测试结果 表2 负载电流测试结果 从上表可以看出在恒转矩输出的频率段(0-50Hz),矢量控制的空载电流几乎只有VF控制的一半,负载时电流也比VF小一些;而且负载切削时,VF控制在初期有很明显的速度下降,而且空载速度和负载速度有比较大的差值。而相对于矢量控制,主轴转速初期虽然也会有下降,但是下降值较小,并且速度会很快回升,最终空载速度和负载速度相差不是很明显。经过上面的调试,相比较原来的VF控制,性能有了很大的改善,无论从空载电流,低速力矩,还是速度的变化,效果都是非常明显的,完全能够满足数控机床的需求。

    时间:2018-11-15 关键词: 机床 变频器 调试 电源技术解析 数控

  • stm32 HardFault_Handler调试及问题查找方法

    stm32 HardFault_Handler调试及问题查找方法STM32出现HardFault_Handler故障的原因主要有两个方面:1、内存溢出或者访问越界。这个需要自己写程序的时候规范代码,遇到了需要慢慢排查。2、堆栈溢出。增加堆栈的大小。出现问题时排查的方法:发生异常之后可首先查看LR寄存器中的值,确定当前使用堆栈为MSP或PSP,然后找到相应堆栈的指针,并在内存中查看相应堆栈里的内容。由于异常发生时,内核将R0~R3、R12、Returnaddress、PSR、LR寄存器依次入栈,其中Return address即为发生异常前PC将要执行的下一条指令地址。在stm32f4xx_it.c中,添加软件断点,一旦调试时出现Hard Fault则会在停在__breakpoint(0)处。void HardFault_Handler(void){if (CoreDebug->DHCSR & 1) {//check C_DEBUGEN == 1 -> Debugger Connected__breakpoint(0);// halt program execution here}while (1){}}DEBUG如下图SP值为0x20008560,查看堆栈里面的值依次为R0~R3、R12、Return address、PSR、LR,例如R0(1027 00 00),显然堆栈后第21个字节到24字节即为Returnaddress,该地址0x0801C907即为异常前PC将要执行的下一条指令地址。当进入HardFault断点后,菜单栏Peripherals >Core Peripherals >FaultReports打开异常发生的报告,查看发生异常的原因。上面的报告发生了BUS FAULT,并将Fault的中断服务转向Hard Fault。相对于检测发生了什么异常,定位异常发生位置显得更重要。(1)打开Call Stack窗口(如下图左侧,断点停在Hard Fault服务程序中)(2)在Call Stack的HardFault_Handler上右键Show CallerCode(有的Keil版本也可以直接双击)这时将跳转到发生异常的源代码位置(如上图),异常发生在p->hour=0这一行。这里错误很明显:指针p尚未为成员变量分配内存空间,直接访问未分配的内粗空间肯定出错。再说明2点:[1]在复杂的情况下,即使定位了异常发生位置也很难容易的改正错误,要学会使用Watch窗口对发生错误的指针变量进行跟踪;[2]在问题不明晰的情况下,尝试分析反汇编代码,就自己遇到的,部分情况下的异常发生在BL等跳转指令处,BL跳转到了不合法的内存地址产生异常

    时间:2018-11-05 关键词: STM32 调试 查找方法

  • 调试体重电路板HX711

    体重电路板HX711 1. 下载程序,如果不正常用万用表测量输出电压是否正常,看BOOT键是否打开,RX、TX是否接对。2. 首先确保程序正确,I/O口对应正确。3. 连接体重计,如果串口接收数据不正常,首先检查称重传感器连线问题;然后用万用表测量模拟输入引脚(通道A+ 通道A-电压)和数字输出引脚(DOUT 串口数据输出)电压变化,可用正常工作的HX711模块作为比较。 4. 正常工作的HX711模块模拟输入电压每增加1KG大概增加0.046mv。数字输出电压每增加1KG增加大概0.1mv。5. 测量对比各电阻电容电压数值及变化,测量三极管Ube是否大概等于0.7V(模电知识)。6. 发现数字输出电压不正常,电压值很小且几乎没变化,然后找解决问题的办法(更换HX711芯片)7.基本原理讲解满量程输出电压=激励电压*灵敏度2.0mv/v。例如:供电电压是5V乘以灵敏度2.0mv/v=满量程10mv,相当于有200KG重力产生时候产生10mv的电压。HX711模块A通道带有128倍信号增益,可以将10mv的电放大128倍,然后采样输出24bitAD转换的值,单片机通过指定时序将24bit数据读出。 

    时间:2018-10-31 关键词: 调试 hx711

  • Stm32_调试出现 Error:Flash Download Failed-"Cortex-M3"

    rror:Flash Download Failed-"Cortex-M3"出现一般有两种情况:1.SWD模式下,Debug菜单中,Reset菜单选项(Autodetect/HWreset/sysresetReq/Vectreset)默认是AutoDetect,改成SysResetReq即可。2.Jtag模式下,主要是芯片大小选错。Flash->Configure Falsh Tools配置窗口,切换到“Utilities"页,按“Setting"按钮进入“Flash download setup"配置窗口,在“Flash download setup"配置窗口点击“Add”按钮,在“Add Flash Programming Algorlthm"窗口,根据你实际使用的芯片选择,若是STM32F103VBT6,应先择"STM32F10X 128kB Flash"。

    时间:2018-10-29 关键词: STM32 调试 error

  • 嵌入式软硬件调试问题记录

    1.RS485使用中发现不能连续收发0.起初调试得出问题是MAX485的TX需要接上拉电阻,并且不能用20K的大电阻,使用10以内的强上拉电阻可以解决。后来发现问题,当0的数量超过10个后又出问题,最终发现问题是共模电压可能过大造成的,将两个485进行共地处理,问题得以解决。2.Zigbee模块问题。上次调试的时候发现有个模块竟然必须接下载器供电的时候才能工作,接其他的电源就无法工作,最终调试的时候发现是由于有个模块的复位端有问题,一直处在复位状态,因此无法运行,将复位端直接接电源就解决了。3.LM331 VFC,电压频率转换。4.今天用自己设计的CPLD驱动的4.3'TFT ,上面附带了TF卡座,弄了一晚上没有初始化成功,最终发现由于背光开启后,3.3V电源电压被拉低到3.0V左右,导致TF卡无法正常工作.5.使用500ma的可恢复保险给STM32供电,发现基准源电源漂动很大,并且3.3V电源也在波动,测量发现将可恢复保险接成0欧电阻即可解决此问题.6.RS485在没有使用隔离模块的时候最好共地,如果使用了隔离,那么就无需共地,有时候共地也会造成很大的噪声干扰.

    时间:2018-10-18 关键词: 调试 硬件问题

  • 体重电路板HX711调试

    体重电路板HX711 1. 下载程序,如果不正常用万用表测量输出电压是否正常,看BOOT键是否打开,RX、TX是否接对。2. 首先确保程序正确,I/O口对应正确。3. 连接体重计,如果串口接收数据不正常,首先检查称重传感器连线问题;然后用万用表测量模拟输入引脚(通道A+ 通道A-电压)和数字输出引脚(DOUT 串口数据输出)电压变化,可用正常工作的HX711模块作为比较。 4. 正常工作的HX711模块模拟输入电压每增加1KG大概增加0.046mv。数字输出电压每增加1KG增加大概0.1mv。5. 测量对比各电阻电容电压数值及变化,测量三极管Ube是否大概等于0.7V(模电知识)。6. 发现数字输出电压不正常,电压值很小且几乎没变化,然后找解决问题的办法(更换HX711芯片)7.基本原理讲解满量程输出电压=激励电压*灵敏度2.0mv/v。例如:供电电压是5V乘以灵敏度2.0mv/v=满量程10mv,相当于有200KG重力产生时候产生10mv的电压。HX711模块A通道带有128倍信号增益,可以将10mv的电放大128倍,然后采样输出24bitAD转换的值,单片机通过指定时序将24bit数据读出。 

    时间:2018-10-11 关键词: 电路板 调试 hx711

  • 使用ldr命令注意事项

    使用ldr命令注意事项

    今天犯了一个小错误,调试了几个小时;最后重新分析了几遍反汇编才发现。万丈高楼平地起、勿以浮沙驻高台。错误代码:.text .global _start _start:     b reset     ldr pc,=und_addr     ldr pc,=swi_addr und_addr:     .word undef swi_addr:     .word swi_handle undef:     ldr sp,=0x32000000 //处理异常调用C函数,设置und模式下的栈,以前是usr模式     //保存现场     stmdb sp!,{r0-r12,lr}     bl print2     //处理异常     mrs r0,cpsr //und模式下的cpsr寄存器,也可以改为输出spsr低5位和usr模式的cpsr相同     ldr r1,=und_string     bl printException     //恢复现场     ldmia sp!,{r0-r12,pc}^ und_string:     .string "undefined instruction exception" .align 4 swi_handle:      ldr sp,=0x33000000 //处理异常调用C函数,设置svc模式下的栈,以前是usr模式     //保存现场     stmdb sp!,{r0-r12,lr}     //处理异常     mrs r0,cpsr //und模式下的cpsr寄存器,也可以改为输出spsr低5位和svc模式的cpsr相同     ldr r1,=swi_string     bl printException     //恢复现场     ldmia sp!,{r0-r12,pc}^ swi_string:     .string "swi exception" .align 4     reset: //关看门狗     ldr r1,=0x53000000     ldr r0,=0     str r0,[r1] //设置时钟     //① 设置锁定时间LOCKTIME     ldr r1,=0x4C000000     ldr r0,=0xFFFFFFFF     str r0,[r1]     //② 设置分频系数,使得FCLK:HCLK:PCLK = 8:4:1     ldr r1,=0x4C000014     ldr r0,=0x5     str r0,[r1]     //③ 根据2440规则,由于②中HDIVN!=0 -> CPU总线模式从快速总线模式到异步模式     mrc p15,0,r0,c1,c0,0     orr r0,r0,#0xc0000000 //R1_nF:OR:R1_iA     mcr p15,0,r0,c1,c0,0     //④ 设置PLL,设置完PLL后,PLL开始工作,锁定时间内CPU停止工作     /* 设置FCLK = 400MHZ,HCLK = 100MHZ, PCLK = 100MHZ       * Mpll(FCLK) = (2*m * Fin) / (p * 2^s)      * m = M(MDIV) (the value for divider M)+ 8,      * p = P(PDIV) (the value for divider P) + 2, s = SDIV      * MDIV = 92(0x5c), PDIV = 1 , SDIV = 1       * FCLK = (2*100*12MHZ) / (3*2^1) = 400MHZ */      ldr r1,=0x4C000004      ldr r0,= ((92<<12) | (1<<4) | (1<<0))      str r0,[r1] //判断启动方式     mov r1,#0 // r1 = 0;     ldr r0,[r1] // r0 = [0];将0地址的值备份     str r1,[r1] // 将0写入0地址     ldr r2,[r1] // 再将0地址的值读出来给r2     cmp r1,r2   // 比较r1和r2,即比较0地址原来的值和写入的值     ldr sp,= 0x40000000 + 4096 // 先假设为nor启动     ldreq sp,= 4096 //如果r1==r2,假设不成立为Nand启动     streq r0,[r1]   // 还原0地址以前的值     bl sdram_init     //bl sdram_init2 //用到有初始值的数组,不是位置无关码         bl copy2sdram        bl clean_bss     //从复位后的SVC模式切换到USR模式     //M[4:0] SVC:10011 USR:10000      mrs r0,cpsr     bic r0,r0,#0xf //修改低四位,进入usr模式     msr cpsr,r0     //设置usr模式下的栈,sp_usr     ldr sp,=0x34000000;     ldr pc,=sdram_next sdram_next:          bl uart0_init     mrs r0,cpsr  //SVC模式下的cpsr寄存器     bl print1     bl print2     swi 0x1  /* 执行此命令, 触发SWI异常, 进入0x8执行 */ und_code:     .word 0xeeadc0de  /* 未定义指令 */     bl main  /* 使用BL命令相对跳转, 程序仍然在NOR/sram执行 */     //ldr pc, =main  /* 绝对跳转, 跳到SDRAM */ halt:     b halt结果:分析:sdram.elf:     file format elf32-littlearm Disassembly of section .text: 30000000: 30000000:   ea00001e    b   3000008030000004:   e59ff110    ldr pc, [pc, #272]  ; 3000011c  30000008:   e59ff110    ldr pc, [pc, #272]  ; 30000120  3000000c: 3000000c:   30000014    andcc   r0, r0, r4, lsl r0 30000010: 30000010:   30000050    andcc   r0, r0, r0, asr r0 ************************************************* 3000011c:   3000000c    andcc   r0, r0, ip 30000120:   30000010    andcc   r0, r0, r0, lsl r0 ************************************************* 30000014: 30000014:   e3a0d432    mov sp, #838860800  ; 0x32000000 30000018:   e92d5fff    stmdb   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr} 3000001c:   eb000103    bl  3000043030000020:   e10f0000    mrs r0, CPSR 30000024:   e59f10f8    ldr r1, [pc, #248]  ; 30000124  30000028:   eb000216    bl  300008883000002c:   e8fd9fff    ldmia   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}^ 30000030: 30000030:   65646e75    strvsb  r6, [r4, #-3701]! ........发生异常的时候,异常向量表中pc没有跳转到相应的执行函数地址,因为我采用了间接的赋值。两次异常都是跳转到und_addr或者swi_addr开始往后面执行,所以两次都执行了undef处理函数。更正测试:①直接赋值到对应执行函数处.text .global _start _start:     b reset     ldr pc,=undef     ldr pc,=swi_handle反汇编:sdram.elf:     file format elf32-littlearm Disassembly of section .text: *************************************** 3000011c:   30000014    andcc   r0, r0, r4, lsl r0 30000120:   30000050    andcc   r0, r0, r0, asr r0 *************************************** 30000000: 30000000:   ea00001e    b   3000008030000004:   e59ff110    ldr pc, [pc, #272]  ; 3000011c  30000008:   e59ff110    ldr pc, [pc, #272]  ; 30000120  3000000c: 3000000c:   30000014    andcc   r0, r0, r4, lsl r0 30000010: 30000010:   30000050    andcc   r0, r0, r0, asr r0 30000014: 30000014:   e3a0d432    mov sp, #838860800  ; 0x32000000 30000018:   e92d5fff    stmdb   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr} 3000001c:   eb000103    bl  3000043030000020:   e10f0000    mrs r0, CPSR 30000024:   e59f10f8    ldr r1, [pc, #248]  ; 30000124  30000028:   eb000216    bl  300008883000002c:   e8fd9fff    ldmia   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}^ 30000030: ... 30000050: 30000050:   e3a0d433    mov sp, #855638016  ; 0x33000000 ...结果: ② 间接赋值.text .global _start _start:     b reset     ldr pc,und_addr     ldr pc,swi_addr反汇编:sdram.elf:     file format elf32-littlearm Disassembly of section .text: 30000000: 30000000:   ea00001e    b   3000008030000004:   e59ff110    ldr pc, [pc, #272]  ; 3000011c  30000008:   e59ff110    ldr pc, [pc, #272]  ; 30000120  ********************* 3000011c:   30000014    andcc   r0, r0, r4, lsl r0 30000120:   30000050    andcc   r0, r0, r0, asr r0 ********************* 3000000c: 3000000c:   30000014    andcc   r0, r0, r4, lsl r0 30000010: 30000010:   30000050    andcc   r0, r0, r0, asr r0 30000014: 30000014:   e3a0d432    mov sp, #838860800  ; 0x32000000 30000018:   e92d5fff    stmdb   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr} 3000001c:   eb000103    bl  3000043030000020:   e10f0000    mrs r0, CPSR 30000024:   e59f10f8    ldr r1, [pc, #248]  ; 30000124  30000028:   eb000216    bl  300008883000002c:   e8fd9fff    ldmia   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}^ 30000030: ... 30000050: 30000050:   e3a0d433    mov sp, #855638016  ; 0x33000000 ...结果: 总结:注意ldr pc,=czg与ldr pc,czg 用法: ①  ldr pc,=czg =》 pc = czg (就是czg标号的地址) ②   ldr pc,czg =》 pc = *(czg) (czg标号地址中放的值)

    时间:2018-10-11 关键词: 调试 汇编

首页  上一页  1 2 3 4 5 6 7 8 9 10 下一页 尾页
发布文章

技术子站

更多

项目外包