+ adapter speed 4000
+}
+
+# get _CHIPNAME from current target
+proc stm32h7x_get_chipname {} {
+ set t [target current]
+ set sep [string last "." $t]
+ if {$sep == -1} {
+ return $t
+ }
+ return [string range $t 0 [expr {$sep - 1}]]
+}
+
+if {[set $_CHIPNAME.DUAL_CORE]} {
+ $_CHIPNAME.cpu1 configure -event examine-end {
+ set _CHIPNAME [stm32h7x_get_chipname]
+ global $_CHIPNAME.USE_CTI
+
+ # Stop watchdog counters during halt
+ # DBGMCU_APB3FZ2 |= WWDG1
+ stm32h7x_dbgmcu_mmw 0x038 0x00000040 0
+ # DBGMCU_APB1LFZ2 |= WWDG2
+ stm32h7x_dbgmcu_mmw 0x040 0x00000800 0
+ # DBGMCU_APB4FZ2 |= WDGLSD1 | WDGLSD2
+ stm32h7x_dbgmcu_mmw 0x058 0x000C0000 0
+
+ if {[set $_CHIPNAME.USE_CTI]} {
+ stm32h7x_cti_start
+ }
+ }
+}
+
+# like mrw, but with target selection
+proc stm32h7x_mrw {used_target reg} {
+ set value ""
+ $used_target mem2array value 32 $reg 1
+ return $value(0)
+}
+
+# like mmw, but with target selection
+proc stm32h7x_mmw {used_target reg setbits clearbits} {
+ set old [stm32h7x_mrw $used_target $reg]
+ set new [expr {($old & ~$clearbits) | $setbits}]
+ $used_target mww $reg $new
+}
+
+# mmw for dbgmcu component registers, it accepts the register offset from dbgmcu base
+# this procedure will use the mem_ap on AP2 whenever possible
+proc stm32h7x_dbgmcu_mmw {reg_offset setbits clearbits} {
+ # use $_CHIPNAME.ap2 if possible, and use the proper dbgmcu base address
+ if {![using_hla]} {
+ set _CHIPNAME [stm32h7x_get_chipname]
+ set used_target $_CHIPNAME.ap2
+ set reg_addr [expr {0xE00E1000 + $reg_offset}]
+ } {
+ set used_target [target current]
+ set reg_addr [expr {0x5C001000 + $reg_offset}]
+ }
+
+ stm32h7x_mmw $used_target $reg_addr $setbits $clearbits
+}
+
+if {[set $_CHIPNAME.USE_CTI]} {
+ # create CTI instances for both cores
+ cti create $_CHIPNAME.cti0 -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0xE0043000
+ cti create $_CHIPNAME.cti1 -dap $_CHIPNAME.dap -ap-num 3 -baseaddr 0xE0043000
+
+ $_CHIPNAME.cpu0 configure -event halted { stm32h7x_cti_prepare_restart_all }
+ $_CHIPNAME.cpu1 configure -event halted { stm32h7x_cti_prepare_restart_all }
+
+ $_CHIPNAME.cpu0 configure -event debug-halted { stm32h7x_cti_prepare_restart_all }
+ $_CHIPNAME.cpu1 configure -event debug-halted { stm32h7x_cti_prepare_restart_all }
+
+ proc stm32h7x_cti_start {} {
+ set _CHIPNAME [stm32h7x_get_chipname]
+
+ # Configure Cores' CTIs to halt each other
+ # TRIGIN0 (DBGTRIGGER) and TRIGOUT0 (EDBGRQ) at CTM_CHANNEL_0
+ $_CHIPNAME.cti0 write INEN0 0x1
+ $_CHIPNAME.cti0 write OUTEN0 0x1
+ $_CHIPNAME.cti1 write INEN0 0x1
+ $_CHIPNAME.cti1 write OUTEN0 0x1
+
+ # enable CTIs
+ $_CHIPNAME.cti0 enable on
+ $_CHIPNAME.cti1 enable on
+ }
+
+ proc stm32h7x_cti_stop {} {
+ set _CHIPNAME [stm32h7x_get_chipname]
+
+ $_CHIPNAME.cti0 enable off
+ $_CHIPNAME.cti1 enable off
+ }
+
+ proc stm32h7x_cti_prepare_restart_all {} {
+ stm32h7x_cti_prepare_restart cti0
+ stm32h7x_cti_prepare_restart cti1
+ }
+
+ proc stm32h7x_cti_prepare_restart {cti} {
+ set _CHIPNAME [stm32h7x_get_chipname]
+
+ # Acknowlodge EDBGRQ at TRIGOUT0
+ $_CHIPNAME.$cti write INACK 0x01
+ $_CHIPNAME.$cti write INACK 0x00
+ }