{"id":1320,"date":"2015-01-06T01:30:01","date_gmt":"2015-01-06T05:30:01","guid":{"rendered":"http:\/\/tim.cexx.org\/?p=1320"},"modified":"2015-01-06T01:30:01","modified_gmt":"2015-01-06T05:30:01","slug":"debugging-a-shorted-pcb-the-lazy-way","status":"publish","type":"post","link":"https:\/\/tim.cexx.org\/?p=1320","title":{"rendered":"Debugging a shorted PCB the lazy way"},"content":{"rendered":"<p>I recently assembled a set of prototype boards for a particular project at my day job, and ran a math- and memory-intensive test loop to test them out. Two of the boards ran the code fine, but one crashed consistently in a bizarre way that suggested corruption or otherwise unreliability of the RAM contents. <\/p>\n<p>Since the other two identical boards worked, a hardware\/assembly defect was the likely explanation. These boards feature a 100-pin TQFP CPU and 48-pin SRAM with 0.5mm lead pitch, all hand-soldered of course, but a good visual inspection turned up no obvious defects.<\/p>\n<p>The first thing I tried was a quick-n-dirty RAM test loop that wrote the entire RAM with an address-specific known value and immediately read it back (in this case, it was just the 32-bit RAM address itself), but this (overly simplistic, it turns out) check didn&#8217;t report any failures. However, I did notice the current reading on my bench supply occasionally spiking from 0.01A to 0.04A. This board uses a low-power ARM micro specifically chosen for efficiency, and should rarely draw more than about 15mA at full tilt, so this was a red flag.<\/p>\n<p>With this in mind, the next thing I did was get a higher-resolution look at what was going on with the current. The CPU vendor provides a sweet energy profiling tool for use with its pre-baked development kits, which also double as programmer and debugger for the kit and external boards. The feature works by sampling input current to the development kit via a sense resistor at high speed, and optionally coupling it to the running program&#8217;s instruction counter via the debugger to estimate energy usage for each function in your program. By uploading a dummy program to the kit that just puts it into a deep sleep, and tying the external board into its VMCU\/GND pins, it can be used with any external target board that draws up to 50mA or so. <\/p>\n<p>Running the memory test again with the profiler active, I got the following:<\/p>\n<figure id=\"attachment_1322\" aria-describedby=\"caption-attachment-1322\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/current.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/current-300x297.png\" alt=\"Current trace\" width=\"300\" height=\"297\" class=\"size-medium wp-image-1322\" srcset=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/current-300x297.png 300w, https:\/\/tim.cexx.org\/wp-content\/uploads\/current-150x150.png 150w, https:\/\/tim.cexx.org\/wp-content\/uploads\/current.png 750w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><figcaption id=\"caption-attachment-1322\" class=\"wp-caption-text\">Current trace as reported by EnergyAware Profiler<\/figcaption><\/figure>\n<p>Again, the kit can supply a max of 50mA or so, and this graph shows a repeating cycle which spends half the time somewhere a bit northward of this. Sure enough, probing the supply voltage with a scope, the voltage drops a bit whenever the overcurrent occurs. A memory test loop should draw a fairly constant current; it shouldn&#8217;t vary with time or data or address as this appears to be doing. So it&#8217;s a safe bet that one of the address or data pins to the external RAM is shorted. But where?<\/p>\n<p>I could begin probing address and data lines to find the ones that toggled at the same rate as the dip on the voltage rail, but on a wild hare (or hair)  picked up our new secret weapon (not the <a href=\"http:\/\/en.wikipedia.org\/wiki\/The_Red_Green_Show#Handyman_Corner\">Handyman&#8217;s Secret Weapon<\/a>), an IR thermal camera.<\/p>\n<p>Just after power-on with the RAM test running, I saw this:<\/p>\n<figure id=\"attachment_1323\" aria-describedby=\"caption-attachment-1323\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/ir-powered.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/ir-powered-300x225.jpg\" alt=\"IR thermal view of the CPU when powered and running the external RAM test\" width=\"300\" height=\"225\" class=\"size-medium wp-image-1323\" srcset=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/ir-powered-300x225.jpg 300w, https:\/\/tim.cexx.org\/wp-content\/uploads\/ir-powered.jpg 320w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><figcaption id=\"caption-attachment-1323\" class=\"wp-caption-text\">IR thermal view of the CPU when powered and running the external RAM test<\/figcaption><\/figure>\n<p>The part immediately to the left of the crosshair is the CPU. It wasn\u2019t detectably warm to the touch, but here it&#8217;s easy enough to see where the die itself sits inside the chip package. There is also an apparent \u2018hotspot\u2019 roughly centered along the lefthand edge of the die. The I\/O pins just next to this hotspot are address lines tied to the RAM. While it isn&#8217;t *always* the case due to the vagaries of chip layout, the GPIO pin drivers are almost always situated at the edges of the die, right next to the pins they drive. This is about as close to a smoking gun as you can get without the actual <a href=\"http:\/\/en.wikipedia.org\/wiki\/Magic_smoke\">smoke<\/a>. While it&#8217;s hard to see exactly which pin or pins this hotspot corresponds to, it does narrow the search quite a bit! For reference, here is how it looks unpowered.<\/p>\n<figure id=\"attachment_1324\" aria-describedby=\"caption-attachment-1324\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/ir-unpowered.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/ir-unpowered-300x225.jpg\" alt=\"IR thermal view of the CPU when unpowered.\" width=\"300\" height=\"225\" class=\"size-medium wp-image-1324\" srcset=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/ir-unpowered-300x225.jpg 300w, https:\/\/tim.cexx.org\/wp-content\/uploads\/ir-unpowered.jpg 320w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><figcaption id=\"caption-attachment-1324\" class=\"wp-caption-text\">IR thermal view of the CPU when unpowered.<\/figcaption><\/figure>\n<p>Scoping a handful of adjacent pins, the issue becomes clear. <\/p>\n<figure id=\"attachment_1325\" aria-describedby=\"caption-attachment-1325\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/probe-edit.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/probe-edit-300x186.jpg\" alt=\"Probing near the hotspot seen on IR.\" width=\"300\" height=\"186\" class=\"size-medium wp-image-1325\" srcset=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/probe-edit-300x186.jpg 300w, https:\/\/tim.cexx.org\/wp-content\/uploads\/probe-edit-1024x636.jpg 1024w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><figcaption id=\"caption-attachment-1325\" class=\"wp-caption-text\">Probing near the hotspot seen on IR.<\/figcaption><\/figure>\n<figure id=\"attachment_1326\" aria-describedby=\"caption-attachment-1326\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/scope-bus-voltages.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/scope-bus-voltages-300x225.jpg\" alt=\"Suspicious &#039;digital&#039; address line voltages near the hotspot.\" width=\"300\" height=\"225\" class=\"size-medium wp-image-1326\" srcset=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/scope-bus-voltages-300x225.jpg 300w, https:\/\/tim.cexx.org\/wp-content\/uploads\/scope-bus-voltages-1024x768.jpg 1024w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><figcaption id=\"caption-attachment-1326\" class=\"wp-caption-text\">Suspicious &#8216;digital&#8217; address line voltages near the hotspot.<\/figcaption><\/figure>\n<p>Two adjacent address lines to the memory, immediately next to the hotspot, show this decidedly non-quite-digital-looking waveform on them (bottom trace), lining up pretty well with the voltage droop (top trace). This points to not one shorted pin (to GND or etc.), but two adjacent pins shorted together, their on-chip drivers fighting one another to produce these intermediate voltages and consuming excess current in the process. A quick beep-test confirms the short.<\/p>\n<p>It turned out to be a hair-thin solder bridge between two adjacent pins on the SRAM, pictured below. Do you see it?<\/p>\n<figure id=\"attachment_1327\" aria-describedby=\"caption-attachment-1327\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/short-invisible.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/short-invisible-300x100.jpg\" alt=\"Take my word for it, there&#039;s a solder bridge in this photo.\" width=\"300\" height=\"100\" class=\"size-medium wp-image-1327\" srcset=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/short-invisible-300x100.jpg 300w, https:\/\/tim.cexx.org\/wp-content\/uploads\/short-invisible-1024x340.jpg 1024w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><figcaption id=\"caption-attachment-1327\" class=\"wp-caption-text\">Take my word for it, there&#8217;s a solder bridge in this photo.<\/figcaption><\/figure>\n<p>Yeah, neither did I at first. It was more visible only at a very specific angle&#8230;<\/p>\n<figure id=\"attachment_1321\" aria-describedby=\"caption-attachment-1321\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/short-visible.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/short-visible-300x119.jpg\" alt=\"Visible short\" width=\"300\" height=\"119\" class=\"size-medium wp-image-1321\" srcset=\"https:\/\/tim.cexx.org\/wp-content\/uploads\/short-visible-300x119.jpg 300w, https:\/\/tim.cexx.org\/wp-content\/uploads\/short-visible-1024x407.jpg 1024w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><figcaption id=\"caption-attachment-1321\" class=\"wp-caption-text\">The short is just visible at this angle<\/figcaption><\/figure>\n<p>Note the other apparent &#8220;stuff&#8221; crossing pins in this angle wasn&#8217;t solder, but remnants of a cotton swab used to clean flux from around the pins.<\/p>\n<p><strong>Mapping the I\/O drivers and other stuff<\/strong><\/p>\n<p>Just for fun, I purposely shorted all the GPIOs available on headers to ground and ran a loop that briefly flipped each one high. Here is the result! Note that not all GPIOs on this board were available on a header (many go to the RAM chip), and they are not necessarily pinned out in a logical numeric order. I haven&#8217;t specifically tested it yet, but the same method should be usable to unintrusively map out the location of on-chip modules (core\/ALU, voltage regulators, AES engines, etc.) that can be exercised individually.<\/p>\n<p><iframe loading=\"lazy\" width=\"420\" height=\"315\" src=\"\/\/www.youtube.com\/embed\/MYd9HUzpmGk\" frameborder=\"0\" allowfullscreen><\/iframe><\/p>\n<p>&lt;pipedream&gt;The day when thermal imaging gets good enough we can use IR attacks instead of power analysis to figure out what a chip is doing (encryption keys, etc.) without decapping it&#8230;&lt;\/pipedream&gt;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I recently assembled a set of prototype boards for a particular project at my day job, and ran a math- and memory-intensive test loop to test them out. Two of the boards ran the code fine, but one crashed consistently in a bizarre way that suggested corruption or otherwise unreliability of the RAM contents. Since [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_FSMCFIC_featured_image_caption":"","_FSMCFIC_featured_image_nocaption":"","_FSMCFIC_featured_image_hide":"","iawp_total_views":24,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1320","post","type-post","status-publish","format-standard","hentry","category-general"],"_links":{"self":[{"href":"https:\/\/tim.cexx.org\/index.php?rest_route=\/wp\/v2\/posts\/1320","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tim.cexx.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tim.cexx.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tim.cexx.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tim.cexx.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1320"}],"version-history":[{"count":3,"href":"https:\/\/tim.cexx.org\/index.php?rest_route=\/wp\/v2\/posts\/1320\/revisions"}],"predecessor-version":[{"id":1330,"href":"https:\/\/tim.cexx.org\/index.php?rest_route=\/wp\/v2\/posts\/1320\/revisions\/1330"}],"wp:attachment":[{"href":"https:\/\/tim.cexx.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1320"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tim.cexx.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1320"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tim.cexx.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1320"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}