Part 2, Topic 1: Introduction to Voltage Glitching (MAIN)¶
SUMMARY: Similarly to clock glitching, inserting brief glitches into the power line of an embedded device can result in skipped instructions and corrupted results. Besides providing a more reliable glitch on some targets when compared to clock glitching, voltage glitching also has the advanatage that the Vcc pins on chips are always accessable. This won’t be covered in this course, but it can also be used to glitch a device asynchronous to its clock.
LEARNING OUTCOMES:
Understanding voltage glitch settings
Building a voltage glitch and crash map.
Modifying glitch circuit to increase glitch success
Voltage Glitch Hardware¶
The ChipWhisperer uses the same hardware block for both voltage and
clock glitching, with the only difference being where the glitch output
is routed to. Instead of routing to HS2, voltage glitching is performed
by routing the glitch to either the glitch_hp
transistor or the
glitch_lp
transistor. This can be done via the following API calls:
scope.io.glitch_hp = True #enable HP glitch
scope.io.glitch_hp = False #disable LP glitch
scope.io.glitch_lp = True #enable LP glitch
scope.io.glitch_lp = False #disable LP glitch
While the hardware block are the same, you’ll need to change how it’s
configued. You wouldn’t want to try routing "clock_xor"
to the
glitch transistor and oscillate Vcc like the device’s clock! Instead,
the following two output settings are best suited to voltage glitching:
"glitch_only"
- insert a glitch for a portion of a clock cycle based onscope.glitch.width
andscope.glitch.offset
"enable_only"
- insert a glitch for an entire clock cycle
Typically, the "enable_only"
setting will be too powerful for most
devices. One situation where it outshines "glitch_only"
is in
glitching asychronous to the target’s clock. An example of this is
glitching a target with an internal clock. In this case, the
ChipWhisperer’s clock can be boosted far above the target’s to insert a
precise glitch, with repeat
functioning as width
and
ext_offset
functioning as offset
.
Voltage Glitching vs. Clock Glitching¶
Voltage glitching has some obvious benefits over clock glitching, such as working for a wider varitey of targets, but its downsides are less obvious. One of the biggest is how much it depends on the actual glitch circuit itself. With clock glitching, it’s relatively easy to insert a glitch - there’s nothing external trying to keep the clock at a certain voltage level. This is very different for a target’s power pins. When we try to drop the power pin to ground, there’s a lot of stuff fighting us to keep the power pin at the correct voltage, such as decoupling capacitors, bulk supply capacitors, and the voltage regulator supplying the voltage. This means when we make small changes to the glitch circuit, the glitch settings and even our ability to insert a glitch at all completely change! Consider glitching a target on the CW308 UFO board. If you switch your coaxial cable length from 20cm to 40 cm, you’ll need to find entirely new glitch settings to repeat the attack (if it’s still even possible). This is quite easy to see on an oscilloscope or using the ChipWhisperer’s ADC: longer cables and lower valued shunt resistors will make the glitch less sharp and increase ringing.
While your first thought might be to go for as sharp a glitch as possible, this often won’t result in a high glitch success rate. If you’re unable to find any working glitches with your current setup, it might be worth changing you hardware setup a bit. For example, on the ChipWhisperer Lite 1 part, you can desolder SJ5 and solder header pins to JP6. Even just connecting these pins with a jumper will have different glitch behaviour than with a soldered SJ5.
You can refer to the training slides for more information about finding good glitch settings, as well as more on the theory side of voltage glitching.
The Lab¶
To introduce you to volatge glitching and find some settings, we’re going to walk back through the clock glitching loop lab. You may want to capture some power traces while you’re first experimenting with glitches to see what effects different glitch widths have on the power trace. Another thing to keep in mind is that targets often won’t tolerate the Vcc pin dropping for an extended period of time without crashing - once you see the target start to crash, you won’t see much else with larger widths.
One thing you might have to change is the glitch repeat value. Depending on how wide your glitch is, the voltage at the power pin may not recover by the time the next glitch is inserted. This can have to effect of increasing subsequent glitches’ strength, which may or may not be desirable. Since glitches inserted with repeat > 1 have different strength, it’s a good idea to scan through ext_offset as well.
Higher Frequency Glitching¶
The XMEGA target, and to a lesser extent the STM32F3, is very difficult to glitch with the default ChipWhisperer settings. Try bumping the clock frequency to 24MHz for the STM32 or 32MHz for the XMEGA and use a repeat 5-10 with both the high power and low power glitches active. You’ll need to adjust the baud rate by the same proportion as the clock.
Another setup that seems to work with the XMEGA is SJ5 unsoldered, JP6 jumpered, high+low power glitch, 32MHz, and repeat=5.
In [1]:
SCOPETYPE = 'OPENADC'
PLATFORM = 'CWLITEARM'
In [2]:
%%bash -s "$PLATFORM"
cd ../../../hardware/victims/firmware/simpleserial-glitch
make PLATFORM=$1 CRYPTO_TARGET=NONE
Out [2]:
SS_VER set to SS_VER_1_1 rm -f -- simpleserial-glitch-CWLITEARM.hex rm -f -- simpleserial-glitch-CWLITEARM.eep rm -f -- simpleserial-glitch-CWLITEARM.cof rm -f -- simpleserial-glitch-CWLITEARM.elf rm -f -- simpleserial-glitch-CWLITEARM.map rm -f -- simpleserial-glitch-CWLITEARM.sym rm -f -- simpleserial-glitch-CWLITEARM.lss rm -f -- objdir/*.o rm -f -- objdir/*.lst rm -f -- simpleserial-glitch.s simpleserial.s stm32f3_hal.s stm32f3_hal_lowlevel.s stm32f3_sysmem.s rm -f -- simpleserial-glitch.d simpleserial.d stm32f3_hal.d stm32f3_hal_lowlevel.d stm32f3_sysmem.d rm -f -- simpleserial-glitch.i simpleserial.i stm32f3_hal.i stm32f3_hal_lowlevel.i stm32f3_sysmem.i . Welcome to another exciting ChipWhisperer target build!! arm-none-eabi-gcc.exe (GNU Arm Embedded Toolchain 9-2020-q2-update) 9.3.1 20200408 (release) Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. . Compiling C: simpleserial-glitch.c arm-none-eabi-gcc -c -mcpu=cortex-m4 -I. -mthumb -mfloat-abi=soft -fmessage-length=0 -ffunction-sections -gdwarf-2 -DSS_VER=SS_VER_1_1 -DSTM32F303xC -DSTM32F3 -DSTM32 -DDEBUG -DHAL_TYPE=HAL_stm32f3 -DPLATFORM=CWLITEARM -DF_CPU=7372800UL -Os -funsigned-char -funsigned-bitfields -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=objdir/simpleserial-glitch.lst -I.././simpleserial/ -I.././hal -I.././hal/stm32f3 -I.././hal/stm32f3/CMSIS -I.././hal/stm32f3/CMSIS/core -I.././hal/stm32f3/CMSIS/device -I.././hal/stm32f4/Legacy -I.././crypto/ -std=gnu99 -MMD -MP -MF .dep/simpleserial-glitch.o.d simpleserial-glitch.c -o objdir/simpleserial-glitch.o . Compiling C: .././simpleserial/simpleserial.c arm-none-eabi-gcc -c -mcpu=cortex-m4 -I. -mthumb -mfloat-abi=soft -fmessage-length=0 -ffunction-sections -gdwarf-2 -DSS_VER=SS_VER_1_1 -DSTM32F303xC -DSTM32F3 -DSTM32 -DDEBUG -DHAL_TYPE=HAL_stm32f3 -DPLATFORM=CWLITEARM -DF_CPU=7372800UL -Os -funsigned-char -funsigned-bitfields -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=objdir/simpleserial.lst -I.././simpleserial/ -I.././hal -I.././hal/stm32f3 -I.././hal/stm32f3/CMSIS -I.././hal/stm32f3/CMSIS/core -I.././hal/stm32f3/CMSIS/device -I.././hal/stm32f4/Legacy -I.././crypto/ -std=gnu99 -MMD -MP -MF .dep/simpleserial.o.d .././simpleserial/simpleserial.c -o objdir/simpleserial.o . Compiling C: .././hal/stm32f3/stm32f3_hal.c arm-none-eabi-gcc -c -mcpu=cortex-m4 -I. -mthumb -mfloat-abi=soft -fmessage-length=0 -ffunction-sections -gdwarf-2 -DSS_VER=SS_VER_1_1 -DSTM32F303xC -DSTM32F3 -DSTM32 -DDEBUG -DHAL_TYPE=HAL_stm32f3 -DPLATFORM=CWLITEARM -DF_CPU=7372800UL -Os -funsigned-char -funsigned-bitfields -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=objdir/stm32f3_hal.lst -I.././simpleserial/ -I.././hal -I.././hal/stm32f3 -I.././hal/stm32f3/CMSIS -I.././hal/stm32f3/CMSIS/core -I.././hal/stm32f3/CMSIS/device -I.././hal/stm32f4/Legacy -I.././crypto/ -std=gnu99 -MMD -MP -MF .dep/stm32f3_hal.o.d .././hal/stm32f3/stm32f3_hal.c -o objdir/stm32f3_hal.o . Compiling C: .././hal/stm32f3/stm32f3_hal_lowlevel.c arm-none-eabi-gcc -c -mcpu=cortex-m4 -I. -mthumb -mfloat-abi=soft -fmessage-length=0 -ffunction-sections -gdwarf-2 -DSS_VER=SS_VER_1_1 -DSTM32F303xC -DSTM32F3 -DSTM32 -DDEBUG -DHAL_TYPE=HAL_stm32f3 -DPLATFORM=CWLITEARM -DF_CPU=7372800UL -Os -funsigned-char -funsigned-bitfields -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=objdir/stm32f3_hal_lowlevel.lst -I.././simpleserial/ -I.././hal -I.././hal/stm32f3 -I.././hal/stm32f3/CMSIS -I.././hal/stm32f3/CMSIS/core -I.././hal/stm32f3/CMSIS/device -I.././hal/stm32f4/Legacy -I.././crypto/ -std=gnu99 -MMD -MP -MF .dep/stm32f3_hal_lowlevel.o.d .././hal/stm32f3/stm32f3_hal_lowlevel.c -o objdir/stm32f3_hal_lowlevel.o . Compiling C: .././hal/stm32f3/stm32f3_sysmem.c arm-none-eabi-gcc -c -mcpu=cortex-m4 -I. -mthumb -mfloat-abi=soft -fmessage-length=0 -ffunction-sections -gdwarf-2 -DSS_VER=SS_VER_1_1 -DSTM32F303xC -DSTM32F3 -DSTM32 -DDEBUG -DHAL_TYPE=HAL_stm32f3 -DPLATFORM=CWLITEARM -DF_CPU=7372800UL -Os -funsigned-char -funsigned-bitfields -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=objdir/stm32f3_sysmem.lst -I.././simpleserial/ -I.././hal -I.././hal/stm32f3 -I.././hal/stm32f3/CMSIS -I.././hal/stm32f3/CMSIS/core -I.././hal/stm32f3/CMSIS/device -I.././hal/stm32f4/Legacy -I.././crypto/ -std=gnu99 -MMD -MP -MF .dep/stm32f3_sysmem.o.d .././hal/stm32f3/stm32f3_sysmem.c -o objdir/stm32f3_sysmem.o . Assembling: .././hal/stm32f3/stm32f3_startup.S arm-none-eabi-gcc -c -mcpu=cortex-m4 -I. -x assembler-with-cpp -mthumb -mfloat-abi=soft -fmessage-length=0 -ffunction-sections -DF_CPU=7372800 -Wa,-gstabs,-adhlns=objdir/stm32f3_startup.lst -I.././simpleserial/ -I.././hal -I.././hal/stm32f3 -I.././hal/stm32f3/CMSIS -I.././hal/stm32f3/CMSIS/core -I.././hal/stm32f3/CMSIS/device -I.././hal/stm32f4/Legacy -I.././crypto/ .././hal/stm32f3/stm32f3_startup.S -o objdir/stm32f3_startup.o . Linking: simpleserial-glitch-CWLITEARM.elf arm-none-eabi-gcc -mcpu=cortex-m4 -I. -mthumb -mfloat-abi=soft -fmessage-length=0 -ffunction-sections -gdwarf-2 -DSS_VER=SS_VER_1_1 -DSTM32F303xC -DSTM32F3 -DSTM32 -DDEBUG -DHAL_TYPE=HAL_stm32f3 -DPLATFORM=CWLITEARM -DF_CPU=7372800UL -Os -funsigned-char -funsigned-bitfields -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=objdir/simpleserial-glitch.o -I.././simpleserial/ -I.././hal -I.././hal/stm32f3 -I.././hal/stm32f3/CMSIS -I.././hal/stm32f3/CMSIS/core -I.././hal/stm32f3/CMSIS/device -I.././hal/stm32f4/Legacy -I.././crypto/ -std=gnu99 -MMD -MP -MF .dep/simpleserial-glitch-CWLITEARM.elf.d objdir/simpleserial-glitch.o objdir/simpleserial.o objdir/stm32f3_hal.o objdir/stm32f3_hal_lowlevel.o objdir/stm32f3_sysmem.o objdir/stm32f3_startup.o --output simpleserial-glitch-CWLITEARM.elf --specs=nano.specs --specs=nosys.specs -T .././hal/stm32f3/LinkerScript.ld -Wl,--gc-sections -lm -Wl,-Map=simpleserial-glitch-CWLITEARM.map,--cref -lm . Creating load file for Flash: simpleserial-glitch-CWLITEARM.hex arm-none-eabi-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature simpleserial-glitch-CWLITEARM.elf simpleserial-glitch-CWLITEARM.hex . Creating load file for EEPROM: simpleserial-glitch-CWLITEARM.eep arm-none-eabi-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex simpleserial-glitch-CWLITEARM.elf simpleserial-glitch-CWLITEARM.eep || exit 0 . Creating Extended Listing: simpleserial-glitch-CWLITEARM.lss arm-none-eabi-objdump -h -S -z simpleserial-glitch-CWLITEARM.elf > simpleserial-glitch-CWLITEARM.lss . Creating Symbol Table: simpleserial-glitch-CWLITEARM.sym arm-none-eabi-nm -n simpleserial-glitch-CWLITEARM.elf > simpleserial-glitch-CWLITEARM.sym Size after: text data bss dec hex filename 5232 8 1296 6536 1988 simpleserial-glitch-CWLITEARM.elf +-------------------------------------------------------- + Default target does full rebuild each time. + Specify buildtarget == allquick == to avoid full rebuild +-------------------------------------------------------- +-------------------------------------------------------- + Built for platform CW-Lite Arm (STM32F3) with: + CRYPTO_TARGET = NONE + CRYPTO_OPTIONS = +--------------------------------------------------------
In [3]:
%run "../../Setup_Scripts/Setup_Generic.ipynb"
Out [3]:
Serial baud rate = 38400
INFO: Found ChipWhisperer😍
In [4]:
fw_path = "../../../hardware/victims/firmware/simpleserial-glitch/simpleserial-glitch-{}.hex".format(PLATFORM)
cw.program_target(scope, prog, fw_path)
Out [4]:
Serial baud rate = 115200
Detected known STMF32: STM32F302xB(C)/303xB(C)
Extended erase (0x44), this can take ten seconds or more
Attempting to program 5239 bytes at 0x8000000
STM32F Programming flash...
STM32F Reading flash...
Verified flash OK, 5239 bytes
Serial baud rate = 38400
In [5]:
if PLATFORM == "CWLITEXMEGA":
scope.clock.clkgen_freq = 32E6
target.baud = 38400*32/7.37
def reboot_flush():
scope.io.pdic = False
time.sleep(0.1)
scope.io.pdic = "high_z"
time.sleep(0.1)
#Flush garbage too
target.flush()
else:
scope.clock.clkgen_freq = 24E6
target.baud = 38400*24/7.37
time.sleep(0.1)
def reboot_flush():
scope.io.nrst = False
time.sleep(0.05)
scope.io.nrst = "high_z"
time.sleep(0.05)
#Flush garbage too
target.flush()
Out [5]:
Serial baud rate = 125047.48982360923
In [6]:
reboot_flush()
scope.arm()
target.write("g\n")
scope.capture()
val = target.simpleserial_read_witherrors('r', 4, glitch_timeout=10)#For loop check
valid = val['valid']
if valid:
response = val['payload']
raw_serial = val['full_response']
error_code = val['rv']
print(val)
Out [6]:
{'valid': True, 'payload': CWbytearray(b'c4 09 00 00'), 'full_response': 'rC4090000n', 'rv': 0}
In [7]:
import chipwhisperer.common.results.glitch as glitch
gc = glitch.GlitchController(groups=["success", "reset", "normal"], parameters=["width", "offset", "ext_offset"])
gc.display_stats()
Out [7]:
In [8]:
scope.glitch.clk_src = "clkgen" # set glitch input clock
scope.glitch.output = "glitch_only" # glitch_out = clk ^ glitch
scope.glitch.trigger_src = "ext_single" # glitch only after scope.arm() called
if PLATFORM == "CWLITEXMEGA":
scope.io.glitch_lp = True
scope.io.glitch_hp = True
elif PLATFORM == "CWLITEARM":
scope.io.glitch_lp = True
scope.io.glitch_hp = True
elif PLATFORM == "CW308_STM32F3":
scope.io.glitch_hp = True
scope.io.glitch_lp = True
Some tips for finding good glitches:
There’s a lot of stuff fighting our glitch this time - unlike the clock line, the Vcc rail isn’t supposed to oscillate! As such shorter glitches will have no effect. A good strategy can often to be to increase the minimum glitch width until you start seeing consistant crashes, then backing off on the width.
The repeat parameter behaves very differently than with voltage glitching - at the boosted clock rate, the Vcc often won’t recover before the next glitch. Try different repeat values as well.
We’ve built in a success/reset measurement into the glitch loop. Once you’ve found some glitch spots, this will help you evaluate which ones are best for your target.
In [9]:
from importlib import reload
import chipwhisperer.common.results.glitch as glitch
from tqdm.notebook import trange
import struct
g_step = 0.4
if PLATFORM=="CWLITEXMEGA":
gc.set_range("width", 45.7, 47.8)
gc.set_range("offset", 2.8, 10)
gc.set_range("ext_offset", 2, 4)
scope.glitch.repeat = 10
elif PLATFORM == "CWLITEARM":
#should also work for the bootloader memory dump
gc.set_range("width", 34.7, 36)
gc.set_range("offset", -41, -30)
gc.set_range("ext_offset", 6, 6)
scope.glitch.repeat = 7
elif PLATFORM == "CW308_STM32F3":
#these specific settings seem to work well for some reason
#also works for the bootloader memory dump
gc.set_range("ext_offset", 9, 12)
gc.set_range("width", 47.6, 49.6)
gc.set_range("offset", -19, -21.5)
scope.glitch.repeat = 5
gc.set_global_step(g_step)
scope.adc.timeout = 0.1
reboot_flush()
sample_size = 1
loff = scope.glitch.offset
lwid = scope.glitch.width
total_successes = 0
for glitch_setting in gc.glitch_values():
scope.glitch.offset = glitch_setting[1]
scope.glitch.width = glitch_setting[0]
scope.glitch.ext_offset = glitch_setting[2]
#print(scope.glitch.ext_offset)
successes = 0
resets = 0
for i in range(10):
target.flush()
if scope.adc.state:
# can detect crash here (fast) before timing out (slow)
print("Trigger still high!")
gc.add("reset", (scope.glitch.width, scope.glitch.offset, scope.glitch.ext_offset))
#Device is slow to boot?
reboot_flush()
resets += 1
scope.arm()
#Do glitch loop
target.write("g\n")
ret = scope.capture()
val = target.simpleserial_read_witherrors('r', 4, glitch_timeout=10)#For loop check
scope.io.glitch_hp = False
scope.io.glitch_hp = True
scope.io.glitch_lp = False
scope.io.glitch_lp = True
if ret:
print('Timeout - no trigger')
gc.add("reset", (scope.glitch.width, scope.glitch.offset, scope.glitch.ext_offset))
resets += 1
#Device is slow to boot?
reboot_flush()
else:
if val['valid'] is False:
gc.add("reset", (scope.glitch.width, scope.glitch.offset, scope.glitch.ext_offset))
reboot_flush()
resets += 1
else:
gcnt = struct.unpack("<I", val['payload'])[0]
if gcnt != 2500: #for loop check
gc.add("success", (scope.glitch.width, scope.glitch.offset, scope.glitch.ext_offset))
successes += 1
else:
gc.add("normal", (scope.glitch.width, scope.glitch.offset, scope.glitch.ext_offset))
if successes > 0:
print("successes = {}, resets = {}, offset = {}, width = {}, ext_offset = {}".format(successes, resets, scope.glitch.offset, scope.glitch.width, scope.glitch.ext_offset))
total_successes += successes
print("Done glitching")
Out [9]:
successes = 1, resets = 4, offset = -40.625, width = 34.765625, ext_offset = 6
ERROR:root:Target did not ack
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
successes = 1, resets = 0, offset = -39.84375, width = 34.765625, ext_offset = 6
Timeout - no trigger
ERROR:root:Target did not ack
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
Timeout - no trigger
successes = 2, resets = 1, offset = -39.0625, width = 34.765625, ext_offset = 6
ERROR:root:Target did not ack
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
Timeout - no trigger
successes = 1, resets = 1, offset = -38.28125, width = 34.765625, ext_offset = 6
ERROR:root:Target did not ack
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
Timeout - no trigger
ERROR:root:Target did not ack
successes = 1, resets = 1, offset = -37.5, width = 34.765625, ext_offset = 6
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
Timeout - no trigger
successes = 1, resets = 1, offset = -37.109375, width = 34.765625, ext_offset = 6
ERROR:root:Target did not ack
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
Timeout - no trigger
successes = 1, resets = 1, offset = -35.9375, width = 34.765625, ext_offset = 6
ERROR:root:Target did not ack
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
ERROR:root:Target did not ack
Timeout - no trigger
successes = 2, resets = 1, offset = -34.375, width = 34.765625, ext_offset = 6
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
Timeout - no trigger
ERROR:root:Target did not ack
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
ERROR:root:Target did not ack
Timeout - no trigger
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
Timeout - no trigger
successes = 2, resets = 2, offset = -33.59375, width = 34.765625, ext_offset = 6
ERROR:root:Target did not ack
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
Timeout - no trigger
successes = 3, resets = 1, offset = -32.8125, width = 34.765625, ext_offset = 6
ERROR:root:Target did not ack
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
Timeout - no trigger
successes = 1, resets = 1, offset = -32.421875, width = 34.765625, ext_offset = 6
successes = 1, resets = 2, offset = -39.0625, width = 35.15625, ext_offset = 6
successes = 1, resets = 0, offset = -38.671875, width = 35.15625, ext_offset = 6
successes = 1, resets = 1, offset = -38.28125, width = 35.15625, ext_offset = 6
successes = 2, resets = 3, offset = -37.890625, width = 35.15625, ext_offset = 6
successes = 2, resets = 1, offset = -36.71875, width = 35.15625, ext_offset = 6
successes = 1, resets = 0, offset = -35.15625, width = 35.15625, ext_offset = 6
successes = 1, resets = 3, offset = -34.375, width = 35.15625, ext_offset = 6
successes = 1, resets = 0, offset = -32.8125, width = 35.15625, ext_offset = 6
successes = 1, resets = 9, offset = -39.453125, width = 35.546875, ext_offset = 6
successes = 1, resets = 9, offset = -34.375, width = 35.546875, ext_offset = 6
successes = 1, resets = 9, offset = -32.8125, width = 35.546875, ext_offset = 6
ERROR:root:Target did not ack
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
Timeout - no trigger
successes = 1, resets = 1, offset = -32.03125, width = 35.546875, ext_offset = 6
successes = 1, resets = 6, offset = -39.84375, width = 35.9375, ext_offset = 6
successes = 2, resets = 6, offset = -39.453125, width = 35.9375, ext_offset = 6
ERROR:root:Target did not ack
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
WARNING:root:Timeout in OpenADC capture(), trigger FORCED
Timeout - no trigger
successes = 1, resets = 6, offset = -32.421875, width = 35.9375, ext_offset = 6
Done glitching
In [10]:
%matplotlib inline
gc.results.plot_2d(plotdots={"success":"+g", "reset":"xr", "normal":None})
Out [10]:

In [11]:
scope.dis()
target.dis()
In [12]:
assert total_successes >= 1