예제 #1
0
    def init(self):
        CortexM.init(self, False)

        # check for flash security
        val = self.transport.readAP(MDM_IDR)
        if val != 0x001c0020:
            logging.error("KL25Z: bad flash ID")
        val = self.transport.readAP(MDM_STATUS)
        if (val & (1 << 2)):
            logging.warning("KL25Z secure state: will try to unlock")
            self.transport.assertReset(True)
            while True:
                self.transport.writeAP(MDM_CTRL, 1)
                val = self.transport.readAP(MDM_STATUS)
                logging.info(val)
                if (val & 1):
                    break
            while True:
                self.transport.writeAP(MDM_CTRL, 0)
                val = self.transport.readAP(MDM_CTRL)
                if (val == 0):
                    break

        logging.info("KL25Z not in secure state")
        self.halt()
        self.setupFPB()
예제 #2
0
 def init(self):
     CortexM.init(self, False)
     
     # check for flash security
     val = self.transport.readAP(MDM_IDR)
     if val != 0x001c0020:
         logging.error("KL25Z: bad flash ID")
     val = self.transport.readAP(MDM_STATUS)
     if (val & (1 << 2)):
         logging.warning("KL25Z secure state: will try to unlock")
         self.transport.assertReset(True)
         while True:
             self.transport.writeAP(MDM_CTRL, 1)
             val = self.transport.readAP(MDM_STATUS)
             logging.info(val)
             if (val & 1):
                 break
         while True:
             self.transport.writeAP(MDM_CTRL, 0)
             val = self.transport.readAP(MDM_CTRL)
             if (val == 0):
                 break
             
     logging.info("KL25Z not in secure state")
     self.halt()
     self.setupFPB()
예제 #3
0
    def resetStopOnReset(self, software_reset=False):
        if self.ignoreReset:
            return

        # Set core up to run some code in RAM that is guaranteed to be valid
        # since FLASH could be corrupted and that is what user is trying to fix.
        self.writeMemory(0x10000000, 0x10087ff0)    # Initial SP
        self.writeMemory(0x10000004, 0x1000000d)    # Reset Handler
        self.writeMemory(0x10000008, 0x1000000d)    # Hard Fault Handler
        self.writeMemory(0x1000000c, 0xe7fee7fe)    # Infinite loop
        self.writeMemory(0x40043100, 0x10000000)    # Shadow 0x0 to RAM

        # Always use software reset for LPC4330 since the hardware version
        # will reset the DAP.
        CortexM.resetStopOnReset(self, True)

        # Map shadow memory to SPIFI FLASH
        self.writeMemory(0x40043100, 0x80000000)

        # The LPC4330 flash init routine can be used to remount FLASH.
        self.ignoreReset = True
        self.flash.init()
        self.ignoreReset = False

        # Set SP and PC based on interrupt vector in SPIFI_FLASH
        sp = self.readMemory(0x14000000)
        pc = self.readMemory(0x14000004)
        self.writeCoreRegisterRaw('sp', sp)
        self.writeCoreRegisterRaw('pc', pc)
예제 #4
0
 def init(self):
 	logging.debug('stm32l486 init')
     CortexM.init(self)
     self.writeMemory(DBGMCU_CR, DBGMCU_VAL)
     self.writeMemory(DBGMCU_APB1_CR1, DBGMCU_APB1_VAL1)
     self.writeMemory(DBGMCU_APB1_CR2, DBGMCU_APB1_VAL2)       
     self.writeMemory(DBGMCU_APB2_CR, DBGMCU_APB2_VAL)
예제 #5
0
 def init(self):
     logging.debug('stm32f051 init')
     CortexM.init(self)
     enclock = self.readMemory(RCC_APB2ENR_CR)
     enclock |= RCC_APB2ENR_DBGMCU
     self.writeMemory(RCC_APB2ENR_CR, enclock)
     self.writeMemory(DBGMCU_APB1_CR, DBGMCU_APB1_VAL)
     self.writeMemory(DBGMCU_APB2_CR, DBGMCU_APB2_VAL)
예제 #6
0
 def init(self):
     logging.debug('stm32f051 init')
     CortexM.init(self)
     enclock = self.readMemory(RCC_APB2ENR_CR)
     enclock |= RCC_APB2ENR_DBGMCU
     self.writeMemory(RCC_APB2ENR_CR, enclock);
     self.writeMemory(DBGMCU_APB1_CR, DBGMCU_APB1_VAL);
     self.writeMemory(DBGMCU_APB2_CR, DBGMCU_APB2_VAL);
예제 #7
0
 def resetStopOnReset(self, software_reset = True):
     """
     perform a reset and stop the core on the reset handler
     """
     # Keep call to CortexM version of resetStopOnReset but make 
     # the default a software reset since a hardware reset does 
     # not work when debugging is enabled
     CortexM.resetStopOnReset(self, software_reset)
예제 #8
0
 def reset(self, software_reset = True):
     """
     reset a core. After a call to this function, the core
     is running
     """
     # Keep call to CortexM version of reset but make the default a
     # software reset since a hardware reset does not work when 
     # debugging is enabled
     CortexM.reset(self, software_reset)
예제 #9
0
    def resetStopOnReset(self, software_reset = None, map_to_user = True):
        CortexM.resetStopOnReset(self, software_reset)

        # Remap to use flash and set SP and SP accordingly
        if map_to_user:
            self.writeMemory(0x40048000, 0x2, 32)
            sp = self.readMemory(0x0)
            pc = self.readMemory(0x4)
            self.writeCoreRegisterRaw('sp', sp)
            self.writeCoreRegisterRaw('pc', pc)
예제 #10
0
    def resetStopOnReset(self, software_reset=False, map_to_user=True):
        CortexM.resetStopOnReset(self)

        # Remap to use flash and set SP and SP accordingly
        if map_to_user:
            self.writeMemory(0x400FC040, 1)
            sp = self.readMemory(0x0)
            pc = self.readMemory(0x4)
            self.writeCoreRegisterRaw("sp", sp)
            self.writeCoreRegisterRaw("pc", pc)
예제 #11
0
    def init(self):
        CortexM.init(self, False, False)
        
        # check for flash security
        val = self.transport.readAP(MDM_IDR)
        if val != self.mdm_idr:
            logging.error("%s: bad MDM-AP IDR (is 0x%08x, expected 0x%08x)", self.part_number, val, self.mdm_idr)
        if self.isLocked():
            logging.warning("%s in secure state: will try to unlock via mass erase", self.part_number)
            # keep the target in reset until is had been erased and halted
            self.transport.assertReset(True)
            if not self.massErase():
                self.transport.assertReset(False)
                logging.error("%s: mass erase failed", self.part_number)
                raise Exception("unable to unlock device")
            # Use the MDM to keep the target halted after reset has been released 
            self.transport.writeAP(MDM_CTRL, MDM_CTRL_DEBUG_REQUEST)
            # Enable debug
            self.writeMemory(DHCSR, DBGKEY | C_DEBUGEN)
            self.transport.assertReset(False)
            while self.transport.readAP(MDM_STATUS) & MDM_STATUS_CORE_HALTED != MDM_STATUS_CORE_HALTED:
                logging.debug("Waiting for mdm halt (erase)")
                sleep(0.01)

            # release MDM halt once it has taken effect in the DHCSR
            self.transport.writeAP(MDM_CTRL, 0)
        else:
            logging.info("%s not in secure state", self.part_number)
        
        # Prevent the target from resetting if it has invalid code
        self.transport.writeAP(MDM_CTRL, MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET)
        while self.transport.readAP(MDM_CTRL) & (MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET) != (MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET):
            self.transport.writeAP(MDM_CTRL, MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET)
        # Enable debug
        self.writeMemory(DHCSR, DBGKEY | C_DEBUGEN)
        # Disable holding the core in reset, leave MDM halt on
        self.transport.writeAP(MDM_CTRL, MDM_CTRL_DEBUG_REQUEST)

        # Wait until the target is halted
        while self.transport.readAP(MDM_STATUS) & MDM_STATUS_CORE_HALTED != MDM_STATUS_CORE_HALTED:
            logging.debug("Waiting for mdm halt")
            sleep(0.01)

        # release MDM halt once it has taken effect in the DHCSR
        self.transport.writeAP(MDM_CTRL, 0)
        
        # sanity check that the target is still halted
        if self.getState() == TARGET_RUNNING:
            raise Exception("Target failed to stay halted during init sequence")

        self.setupFPB()
        self.setupDWT()
        self.readCoreType()
        self.checkForFPU()
예제 #12
0
 def resetn(self):
     """
     reset a core. After a call to this function, the core
     is running
     """
     #Regular reset will kick NRF out of DBG mode
     logging.debug("target_nrf52.reset: enable reset pin")
     self.writeMemory(RESET, RESET_ENABLE)
     #reset
     logging.debug("target_nrf52.reset: trigger nRST pin")
     CortexM.reset(self)
예제 #13
0
 def resetn(self):
     """
     reset a core. After a call to this function, the core
     is running
     """
     #Regular reset will kick NRF out of DBG mode
     logging.debug("target_nrf52.reset: enable reset pin")
     self.writeMemory(RESET, RESET_ENABLE)
     #reset
     logging.debug("target_nrf52.reset: trigger nRST pin")
     CortexM.reset(self)
예제 #14
0
 def init(self):
     CortexM.init(self, False)
     
     # check for flash security
     val = self.transport.readAP(MDM_IDR)
     if val != self.mdm_idr:
         logging.error("%s: bad MDM-AP IDR (is 0x%08x, expected 0x%08x)", self.part_number, val, self.mdm_idr)
     self.checkSecurity()
     self.halt()
     self.setupFPB()
     self.readCoreType()
     self.checkForFPU()
예제 #15
0
    def init(self):
        CortexM.init(self, False)

        # check for flash security
        val = self.transport.readAP(MDM_IDR)
        if val != self.mdm_idr:
            logging.error("%s: bad MDM-AP IDR (is 0x%08x, expected 0x%08x)",
                          self.part_number, val, self.mdm_idr)
        self.checkSecurity()
        self.halt()
        self.setupFPB()
        self.readCoreType()
        self.checkForFPU()
예제 #16
0
    def __init__(self,
                 fw_path,
                 target_name=None,
                 map_address=None,
                 irq_no=None):
        try:
            makedirs(ELFGenerator.BUILD_FOLDER)
        except FileExistsError:
            pass

        # TODO: figure out target from target name parameter
        self.target_name = target_name
        self.target = CortexM(7, map_address, irq_no)

        self.fw_path = fw_path
        map_address, stack_pointer, entry_point, irq_no = self.target.determine_information(
            self.fw_path)
        self.entry_point = entry_point
예제 #17
0
 def init(self):
     logging.debug('stm32f301K8 init')
     CortexM.init(self)
     self.writeMemory(DBGMCU_CR, DBGMCU_VAL)
     self.writeMemory(DBGMCU_APB1_CR, DBGMCU_APB1_VAL)
     self.writeMemory(DBGMCU_APB2_CR, DBGMCU_APB2_VAL)
예제 #18
0
 def reset(self):
     # halt processor
     self.halt()
     # not remap 0x0000-0x0020 to anything but the flash
     self.writeMemory(0x400FC040, 1)
     CortexM.reset(self)
예제 #19
0
class ELFGenerator:
    BUILD_FOLDER = '__build/'
    C_SOURCE_FILE = BUILD_FOLDER + 'main.c'
    LD_SCRIPT_FILE = BUILD_FOLDER + 'tmp.ld'

    INITIAL_C_CODE = '''
typedef unsigned char u8_t;
typedef unsigned short u16_t;
typedef unsigned int u32_t;
typedef void (*handler_void_void_t)(void);
'''

    TYPE_TO_BYTE_SIZE = {
        'u8_t': 1,
        'u16_t': 2,
        'u32_t': 4,
        'handler_void_void_t': 4,  # TODO: handle 64-bit arch
    }

    PREFIX = 'arm-none-eabi-'
    GCC = PREFIX + 'gcc'
    OBJCOPY = PREFIX + 'objcopy'

    def __init__(self,
                 fw_path,
                 target_name=None,
                 map_address=None,
                 irq_no=None):
        try:
            makedirs(ELFGenerator.BUILD_FOLDER)
        except FileExistsError:
            pass

        # TODO: figure out target from target name parameter
        self.target_name = target_name
        self.target = CortexM(7, map_address, irq_no)

        self.fw_path = fw_path
        map_address, stack_pointer, entry_point, irq_no = self.target.determine_information(
            self.fw_path)
        self.entry_point = entry_point

    def generate(self, elf_path):
        ld = LinkerScript()
        ld.set_entry_point('reset', self.entry_point)
        mmap = self.target.get_memory_map()
        syms = self.target.get_registers()

        for m in mmap:
            ld.add_memory(*m)
        for s in syms:
            ld.add_symbol(s[0], s[1])
        c_code = self._generate_c_file(syms)
        ld_script = str(ld)

        open(ELFGenerator.C_SOURCE_FILE, 'w').write(c_code)
        open(ELFGenerator.LD_SCRIPT_FILE, 'w').write(ld_script)

        self._compile_file(ELFGenerator.C_SOURCE_FILE,
                           ELFGenerator.LD_SCRIPT_FILE, elf_path)
        self._update_section('.vt', self.fw_path, elf_path)

    def _generate_c_file(self, structures):
        c = ELFGenerator.INITIAL_C_CODE
        for s_name, s_address, s_members in structures:
            c += 'struct _%s {\n' % s_name
            current_address = s_address
            for m_name, m_type, m_address, m_description in sorted(
                    s_members, key=lambda s: s[2]):
                # Handle padding here
                if current_address != m_address:
                    c += '  /* 0x%08x */  u8_t __padding__0x%08x_0x%08x[0x%08x];\n' % (
                        current_address, current_address, m_address,
                        m_address - current_address)
                    current_address = m_address

                c += '  /* 0x%08x */  %s %s; // %s\n' % (m_address, m_type,
                                                         m_name, m_description)
                if not m_type in ELFGenerator.TYPE_TO_BYTE_SIZE:
                    raise Exception('Unknown type used: %s' % m_type)
                current_address += ELFGenerator.TYPE_TO_BYTE_SIZE[m_type]
            c += '} %s __attribute__((section(".%s")));\n' % (s_name.upper(),
                                                              s_name)

        return c

    def _compile_file(self, source_file, link_script, elf_file):
        compiler = [ELFGenerator.GCC]
        cflags = [
            '-ggdb3', '-nostdlib', '-nostartfiles',
            '-mcpu=%s' % self.target_name, '-mthumb'
        ]
        linker_script = [link_script]
        source_file = [source_file]
        output = ['-o', elf_file]
        call(compiler + cflags + linker_script + source_file + linker_script +
             output)

    def _update_section(self, section_name, raw_file, elf_file):
        objcopy = [ELFGenerator.OBJCOPY]
        objflags = [
            '--update-section',
            '%s=%s' % (section_name, raw_file), elf_file
        ]
        call(objcopy + objflags)
예제 #20
0
 def reset(self, software_reset=False):
     # Always use software reset for LPC4330 since the hardware version
     # will reset the DAP.
     CortexM.reset(self, True)
예제 #21
0
 def reset(self, software_reset=False):
     CortexM.reset(self, False)
예제 #22
0
 def __init__(self, transport):
     CortexM.__init__(self, transport)
     self.auto_increment_page_size = 0x400
예제 #23
0
 def resetn(self):
     """
     reset a core. After a call to this function, the core
     is running
     """
     CortexM.reset(self)
예제 #24
0
 def resetn(self):
     """
     reset a core. After a call to this function, the core
     is running
     """
     CortexM.reset(self)
예제 #25
0
 def init(self):
     logging.debug('stm32f103rc init')
     CortexM.init(self)
     self.writeMemory(DBGMCU_CR, DBGMCU_VAL);
예제 #26
0
 def resetStopOnReset(self, software_reset=False):
     # halt processor
     self.halt()
     # not remap 0x0000-0x0020 to anything but the flash
     self.writeMemory(0x400FC040, 1)
     CortexM.resetStopOnReset(self)
예제 #27
0
 def init(self):
 	logging.debug('stm32f103rc init')
     CortexM.init(self)
     self.writeMemory(DBGMCU_CR, DBGMCU_VAL);
예제 #28
0
 def reset(self, software_reset = False):
     # halt processor
     self.halt()
     # not remap 0x0000-0x0020 to anything but the flash
     self.writeMemory(0x400FC040, 1)
     CortexM.reset(self, False)
예제 #29
0
 def __init__(self, transport):
     CortexM.__init__(self, transport)
     self.auto_increment_page_size = 0x1000
예제 #30
0
 def reset(self, software_reset=False):
     CortexM.reset(self, False)
예제 #31
0
 def init(self):
     logging.debug('stm32f405 init')
     CortexM.init(self)
     self.writeMemory(DBGMCU_CR, DBGMCU_VAL)
     self.writeMemory(DBGMCU_APB1_CR, DBGMCU_APB1_VAL)
     self.writeMemory(DBGMCU_APB2_CR, DBGMCU_APB2_VAL)
예제 #32
0
    def init(self):
        CortexM.init(self, initial_setup=True, bus_accessible=False)

        # check MDM-AP ID
        val = self.dap.readAP(MDM_IDR)
        if val != self.mdm_idr:
            logging.error("%s: bad MDM-AP IDR (is 0x%08x, expected 0x%08x)", self.part_number, val, self.mdm_idr)

        # check for flash security
        isLocked = self.isLocked()
        if isLocked:
            if self.do_auto_unlock:
                logging.warning("%s in secure state: will try to unlock via mass erase", self.part_number)
                # keep the target in reset until is had been erased and halted
                self.link.assert_reset(True)
                if not self.massErase():
                    self.link.assert_reset(False)
                    logging.error("%s: mass erase failed", self.part_number)
                    raise Exception("unable to unlock device")
                # Use the MDM to keep the target halted after reset has been released
                self.dap.writeAP(MDM_CTRL, MDM_CTRL_DEBUG_REQUEST)
                # Enable debug
                self.writeMemory(CortexM.DHCSR, CortexM.DBGKEY | CortexM.C_DEBUGEN)
                self.link.assert_reset(False)
                while self.dap.readAP(MDM_STATUS) & MDM_STATUS_CORE_HALTED != MDM_STATUS_CORE_HALTED:
                    logging.debug("Waiting for mdm halt (erase)")
                    sleep(0.01)

                # release MDM halt once it has taken effect in the DHCSR
                self.dap.writeAP(MDM_CTRL, 0)

                isLocked = False
            else:
                logging.warning("%s in secure state: not automatically unlocking", self.part_number)
        else:
            logging.info("%s not in secure state", self.part_number)

        # Can't do anything more if the target is secure
        if isLocked:
            return

        if self.halt_on_connect:
            # Prevent the target from resetting if it has invalid code
            self.dap.writeAP(MDM_CTRL, MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET)
            while self.dap.readAP(MDM_CTRL) & (MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET) != (MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET):
                self.dap.writeAP(MDM_CTRL, MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET)
            # Enable debug
            self.writeMemory(CortexM.DHCSR, CortexM.DBGKEY | CortexM.C_DEBUGEN)
            # Disable holding the core in reset, leave MDM halt on
            self.dap.writeAP(MDM_CTRL, MDM_CTRL_DEBUG_REQUEST)

            # Wait until the target is halted
            while self.dap.readAP(MDM_STATUS) & MDM_STATUS_CORE_HALTED != MDM_STATUS_CORE_HALTED:
                logging.debug("Waiting for mdm halt")
                sleep(0.01)

            # release MDM halt once it has taken effect in the DHCSR
            self.dap.writeAP(MDM_CTRL, 0)

            # sanity check that the target is still halted
            if self.getState() == Target.TARGET_RUNNING:
                raise Exception("Target failed to stay halted during init sequence")

        CortexM.init(self, initial_setup=False, bus_accessible=True)
예제 #33
0
    def init(self):
        CortexM.init(self, False, False)

        # check for flash security
        val = self.transport.readAP(MDM_IDR)
        if val != self.mdm_idr:
            logging.error("%s: bad MDM-AP IDR (is 0x%08x, expected 0x%08x)",
                          self.part_number, val, self.mdm_idr)
        if self.isLocked():
            logging.warning(
                "%s in secure state: will try to unlock via mass erase",
                self.part_number)
            # keep the target in reset until is had been erased and halted
            self.transport.assertReset(True)
            if not self.massErase():
                self.transport.assertReset(False)
                logging.error("%s: mass erase failed", self.part_number)
                raise Exception("unable to unlock device")
            # Use the MDM to keep the target halted after reset has been released
            self.transport.writeAP(MDM_CTRL, MDM_CTRL_DEBUG_REQUEST)
            # Enable debug
            self.writeMemory(DHCSR, DBGKEY | C_DEBUGEN)
            self.transport.assertReset(False)
            while self.transport.readAP(
                    MDM_STATUS
            ) & MDM_STATUS_CORE_HALTED != MDM_STATUS_CORE_HALTED:
                logging.debug("Waiting for mdm halt (erase)")
                sleep(0.01)

            # release MDM halt once it has taken effect in the DHCSR
            self.transport.writeAP(MDM_CTRL, 0)
        else:
            logging.info("%s not in secure state", self.part_number)

        # Prevent the target from resetting if it has invalid code
        self.transport.writeAP(
            MDM_CTRL, MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET)
        while self.transport.readAP(MDM_CTRL) & (
                MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET) != (
                    MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET):
            self.transport.writeAP(
                MDM_CTRL, MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET)
        # Enable debug
        self.writeMemory(DHCSR, DBGKEY | C_DEBUGEN)
        # Disable holding the core in reset, leave MDM halt on
        self.transport.writeAP(MDM_CTRL, MDM_CTRL_DEBUG_REQUEST)

        # Wait until the target is halted
        while self.transport.readAP(
                MDM_STATUS) & MDM_STATUS_CORE_HALTED != MDM_STATUS_CORE_HALTED:
            logging.debug("Waiting for mdm halt")
            sleep(0.01)

        # release MDM halt once it has taken effect in the DHCSR
        self.transport.writeAP(MDM_CTRL, 0)

        # sanity check that the target is still halted
        if self.getState() == TARGET_RUNNING:
            raise Exception(
                "Target failed to stay halted during init sequence")

        self.setupFPB()
        self.setupDWT()
        self.readCoreType()
        self.checkForFPU()
예제 #34
0
 def resetStopOnReset(self):
     # halt processor
     self.halt()
     # not remap 0x0000-0x0020 to anything but the flash
     self.writeMemory(0x400FC040, 1)
     CortexM.resetStopOnReset(self)
예제 #35
0
    def init(self):
        CortexM.init(self, initial_setup=True, bus_accessible=False)

        # check MDM-AP ID
        val = self.transport.readAP(MDM_IDR)
        if val != self.mdm_idr:
            logging.error("%s: bad MDM-AP IDR (is 0x%08x, expected 0x%08x)",
                          self.part_number, val, self.mdm_idr)

        # check for flash security
        isLocked = self.isLocked()
        if isLocked:
            if self.do_auto_unlock:
                logging.warning(
                    "%s in secure state: will try to unlock via mass erase",
                    self.part_number)
                # keep the target in reset until is had been erased and halted
                self.transport.assertReset(True)
                if not self.massErase():
                    self.transport.assertReset(False)
                    logging.error("%s: mass erase failed", self.part_number)
                    raise Exception("unable to unlock device")
                # Use the MDM to keep the target halted after reset has been released
                self.transport.writeAP(MDM_CTRL, MDM_CTRL_DEBUG_REQUEST)
                # Enable debug
                self.writeMemory(CortexM.DHCSR,
                                 CortexM.DBGKEY | CortexM.C_DEBUGEN)
                self.transport.assertReset(False)
                while self.transport.readAP(
                        MDM_STATUS
                ) & MDM_STATUS_CORE_HALTED != MDM_STATUS_CORE_HALTED:
                    logging.debug("Waiting for mdm halt (erase)")
                    sleep(0.01)

                # release MDM halt once it has taken effect in the DHCSR
                self.transport.writeAP(MDM_CTRL, 0)

                isLocked = False
            else:
                logging.warning(
                    "%s in secure state: not automatically unlocking",
                    self.part_number)
        else:
            logging.info("%s not in secure state", self.part_number)

        # Can't do anything more if the target is secure
        if isLocked:
            return

        if self.halt_on_connect:
            # Prevent the target from resetting if it has invalid code
            self.transport.writeAP(
                MDM_CTRL, MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET)
            while self.transport.readAP(MDM_CTRL) & (
                    MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET) != (
                        MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET):
                self.transport.writeAP(
                    MDM_CTRL,
                    MDM_CTRL_DEBUG_REQUEST | MDM_CTRL_CORE_HOLD_RESET)
            # Enable debug
            self.writeMemory(CortexM.DHCSR, CortexM.DBGKEY | CortexM.C_DEBUGEN)
            # Disable holding the core in reset, leave MDM halt on
            self.transport.writeAP(MDM_CTRL, MDM_CTRL_DEBUG_REQUEST)

            # Wait until the target is halted
            while self.transport.readAP(
                    MDM_STATUS
            ) & MDM_STATUS_CORE_HALTED != MDM_STATUS_CORE_HALTED:
                logging.debug("Waiting for mdm halt")
                sleep(0.01)

            # release MDM halt once it has taken effect in the DHCSR
            self.transport.writeAP(MDM_CTRL, 0)

            # sanity check that the target is still halted
            if self.getState() == Target.TARGET_RUNNING:
                raise Exception(
                    "Target failed to stay halted during init sequence")

        CortexM.init(self, initial_setup=False, bus_accessible=True)