Repository: pyocd/pyocd
Issue: Unhandled exception when breakpoint is hit in Handler mode

I'm using pyOCD v0.21.1 in combination with an STM32L072 MCU, for wich pyocd support comes from a cmsis pack I obtained using the pyocd pack subcommand.
I run a debugging session with
`pyocd gdbserver --target stm32l072cz`

Every time a breakpoint is triggered when the Cortex is executing in handler mode, an unhandled TypeError exception occurs (please note that I also use FreeRTOS in the code being debugged):

> 0001739:WARNING:cmsis_pack:Page size (1024) is larger than sector size (128) for flash region IROM1; reducing page size to 128
> 0001742:INFO:board:Target type is stm32l072cz
> 0001842:INFO:dap:DP IDR = 0x0bc11477 (v1 MINDP rev0)
> 0001962:INFO:ap:AP#0 IDR = 0x04770031 (AHB-AP var3 rev0)
> 0002062:INFO:rom_table:AP#0 ROM table #0 @ 0xf0000000 (designer=020 part=447)
> 0002078:INFO:rom_table:[0]<e00ff000:ROM class=1 designer=43b part=4c0>
> 0002078:INFO:rom_table:  AP#0 ROM table #1 @ 0xe00ff000 (designer=43b part=4c0)
> 0002094:INFO:rom_table:  [0]<e000e000:SCS-M0+ class=14 designer=43b part=008>
> 0002104:INFO:rom_table:  [1]<e0001000:DWT-M0+ class=14 designer=43b part=00a>
> 0002115:INFO:rom_table:  [2]<e0002000:BPU class=14 designer=43b part=00b>
> 0002123:INFO:cortex_m:CPU core #0 is Cortex-M0+ r0p1
> 0002137:INFO:dwt:2 hardware watchpoints
> 0002151:INFO:fpb:4 hardware breakpoints, 0 literal comparators
> 0002182:INFO:server:Semihost server started on port 4444
> 0002183:INFO:gdbserver:GDB server started on port 3333
> 0004851:INFO:gdbserver:One client connected!
> 0005079:INFO:gdbserver:Attempting to load FreeRTOS
> 0005083:INFO:gdbserver:FreeRTOS loaded successfully
> 0600975:ERROR:gdbserver:Unhandled exception in handle_message: 'NoneType' object is not iterable
> Traceback (most recent call last):
>   File "pyocd/gdbserver/gdbserver.py", line 549, in handle_message
>     reply = handler(msg[msgStart:])
>   File "pyocd/gdbserver/gdbserver.py", line 1023, in handle_query
>     resp = self.handle_query_xml(b'threads', int(data[0], 16), int(data[1].split(b'#')[0], 16))
>   File "pyocd/gdbserver/gdbserver.py", line 1210, in handle_query_xml
>     xml = self.get_threads_xml()
>   File "pyocd/gdbserver/gdbserver.py", line 1315, in get_threads_xml
>     t.text = thread.description
>   File "pyocd/rtos/common.py", line 92, in description
>     return self._target_context.core.exception_number_to_name(ipsr)
>   File "pyocd/coresight/cortex_m.py", line 1298, in exception_number_to_name
>     if self.session.target.irq_table:
>   File "pyocd/core/coresight_target.py", line 367, in irq_table
>     [i for p in self.svd_device.peripherals for i in p.interrupts]}
>   File "pyocd/core/coresight_target.py", line 367, in <listcomp>
>     [i for p in self.svd_device.peripherals for i in p.interrupts]}
> TypeError: 'NoneType' object is not iterable

I looked into this a little bit myself, and the problem can be traced further back to the "_lookup_possibly_derived_attribute" method of the SVDElement class which returns "None" when it cannot find the "interrupts" attribute in SVDElement from which the currently considered SVDElement is derived. 

I applied the following local fix to alleviate the problem. I changed the following line
https://github.com/mbedmicro/pyOCD/blob/0965f7f038622ef1d933af5c6916c482a28244ff/pyocd/debug/svd/model.py#L94
to 
` if derived_value is not NOT_PRESENT and derived_value is not None: 
`
I did not set up a pull request because I'm not sure if this is the correct way to fix this issue (perhaps the fix should be in the list comprehension as to not break the interface of the "_lookup_possibly_derived_attribute"). 

Changed files:
pyocd/debug/svd/model.py

diff --git a/pyocd/debug/svd/model.py b/pyocd/debug/svd/model.py
index 7507a84d..2018a33a 100644
--- a/pyocd/debug/svd/model.py
+++ b/pyocd/debug/svd/model.py
@@ -91,7 +91,7 @@ class SVDElement(object):
         # if there is a derivedFrom, check there first
         elif derived_from is not None:
             derived_value = getattr(derived_from, "_{}".format(attr), NOT_PRESENT)
-            if derived_value is not NOT_PRESENT:
+            if (derived_value is not NOT_PRESENT) and (derived_value is not None):
                 return derived_value
 
         # for some attributes, try to grab from parent