From c81cb4aa2d2b85a513f58d2ddbc492f606473c77 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 28 Sep 2023 03:37:03 -0500 Subject: [PATCH] tcl/target: Add support for TI MSPM0 Add basic support for Texas Instruments MSPM0L, C and G family of Cortex-M0 based micro-controllers. Change-Id: If2b5b1eca001f74d501ede67ec621c7497548a85 Co-developed-by: Henry Nguyen Signed-off-by: Henry Nguyen Signed-off-by: Nishanth Menon Reviewed-on: https://review.openocd.org/c/openocd/+/8385 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: zapb --- doc/openocd.texi | 20 ++++ tcl/target/ti_mspm0.cfg | 199 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 219 insertions(+) create mode 100644 tcl/target/ti_mspm0.cfg diff --git a/doc/openocd.texi b/doc/openocd.texi index 68c7a825b..386528a9d 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -7438,6 +7438,7 @@ flash bank $_FLASHNAME mspm0 0 0 0 0 $_TARGETNAME halt flash erase_sector 0 0 last flash write_image MAIN.bin 0x0 +mspm0_board_reset @end example @item @b{To erase and program the NONMAIN region:} @@ -7445,10 +7446,29 @@ flash write_image MAIN.bin 0x0 halt flash erase_sector 1 0 last flash write_image NONMAIN.bin 0x41C00000 +mspm0_board_reset @end example @end itemize +@deffn {TCL proc} {mspm0_board_reset} +Performs an nRST toggle on the device. +@end deffn + +@deffn {TCL proc} {mspm0_mass_erase} +Sends the mass erase command to the SEC-AP mailbox and then performs +an nRST toggle. Once the command has been fully processed by the ROM, +all MAIN memory will be erased. NOTE: This command is not supported +on MSPM0C* family of devices. +@end deffn + +@deffn {TCL proc} {mspm0_factory_reset} +Sends the factory reset command to the SEC-AP mailbox and then performs +an nRST toggle. Once the command has been fully processed by the ROM, +all MAIN memory will be erased and NONMAIN will be reset to its default +values. +@end deffn + @end deffn @deffn {Flash Driver} {niietcm4} diff --git a/tcl/target/ti_mspm0.cfg b/tcl/target/ti_mspm0.cfg new file mode 100644 index 000000000..4e9b89c1f --- /dev/null +++ b/tcl/target/ti_mspm0.cfg @@ -0,0 +1,199 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023-2025 Texas Instruments Incorporated - https://www.ti.com/ +# +# Texas Instruments MSPM0L/G - ARM Cortex-M0 @ 32MHz +# https://www.ti.com/microcontrollers-mcus-processors/arm-based-microcontrollers/arm-cortex-m0-mcus/overview.html +# + +source [find bitsbytes.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + # Meant to work with MSPM0L and MSPM0G class of devices. + set _CHIPNAME mspm0x +} + +if { [info exists CPUTAPID] } { + set _DAP_TAPID $CPUTAPID +} else { + set _DAP_TAPID 0x4ba00477 +} + +if { [info exists DAP_SWD_ID] } { + set _DAP_SWD_ID $DAP_SWD_ID +} else { + set _DAP_SWD_ID 0x2ba01477 +} + +source [find target/swj-dp.tcl] + +# MSPM0 only supports swd, so set it here and save a line for custom boards +transport select swd + +set _DAP_ID $_DAP_SWD_ID + +swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_DAP_ID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap + +if { [info exists WORKAREABASE] } { + set _WORKAREABASE $WORKAREABASE +} else { + set _WORKAREABASE 0x20000000 +} +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + # Smallest SRAM size is 1K SRAM. + set _WORKAREASIZE 0x400 +} + +# +# MSPM0 Debug SubSystem Mailbox (DSSM) Communication helpers +# + +proc _mspm0_wait_for_dssm_response {command} { + # Wait for SECAP::RCR rx_valid to be set + set timeout 1000 + while { [expr { [$::_CHIPNAME.dap apreg 2 0xc] & 0x1}] != 0x1 } { + sleep 1 + set timeout [expr {$timeout - 1}] + if { $timeout == 0 } { + set rcr [$::_CHIPNAME.dap apreg 2 0xc] + return -code error [format "MSPM0 SECAP RCR=0x%08x timeout rx_valid" $rcr] + } + } + + # Read SECAP::RXD to clear the RX_VALID bit + set rxd [$::_CHIPNAME.dap apreg 2 0x8] + # Read SECAP::RCR + set rcr [$::_CHIPNAME.dap apreg 2 0xc] + + # Check if we got successful response. This is denoted as: + # 8 LSBits of $command should matchup with SECAP::RCR + # and + # SECAP::RXD should be 0x10003 + if { ([expr { $command & 0xff}] == $rcr) && ($rxd == 0x10003) } { + return 0 + } + + # Provide some debug log for users to report back if CMD fails. + return -code error [format "MSPM0 SECAP CMD FAIL! RXD: 0x%08X RCR: 0x%08X" $rxd $rcr] +} + +proc _mspm0_dssm_command {command} { + # SECAP::TCR = command + $::_CHIPNAME.dap apreg 2 0x4 $command + # SECAP::TDR = 0x0 + $::_CHIPNAME.dap apreg 2 0x0 0x0 + # Read SECAP::RCR and RXD to clear up any prev pending reads + set rxd [$::_CHIPNAME.dap apreg 2 0x8] + set rcr [$::_CHIPNAME.dap apreg 2 0xc] + # Make sure everything is synced + sleep 1000 + # Trigger nRST + mspm0_board_reset + + # Wait for ROM to do it's magic and respond back + set res [_mspm0_wait_for_dssm_response $command] + if { $res } { + return $res + } + # Paranoid.. make sure ROM does what it is meant to do + # RX valid should have been cleared after the operation is + # complete + sleep 1000 + + # Trigger nRST to get back to sane system + mspm0_board_reset + sleep 1000 + + return 0 +} + +# NOTE: Password authentication scheme is NOT supported atm. +# mspm0_factory_reset: Factory reset the board +proc mspm0_factory_reset {} { + set res [_mspm0_dssm_command 0x020a] + if { $res } { + echo "Factory Reset failed!" + } else { + echo "Factory reset success! Halting processor" + # We need to halt the processor else the WDT fires! + halt + } + return $res +} + +add_help_text mspm0_factory_reset "Force Factory reset to recover 'bricked' board" + +# NOTE: Password authentication scheme is NOT supported atm. +# mspm0_mass_erase: Mass erase flash +proc mspm0_mass_erase {} { + set res [_mspm0_dssm_command 0x020c] + if { $res } { + echo "Mass Erase failed!" + } else { + echo "Mass Erase success! Halting Processor" + # We need to halt the processor else the WDT fires! + halt + } + return $res +} + +add_help_text mspm0_mass_erase "Mass erase flash" + +# mspm0_start_bootloader: Ask explicitly for bootloader startup +proc mspm0_start_bootloader {} { + set res [_mspm0_dssm_command 0x0108] + if { $res } { + echo "Start BL failed!" + } + return $res +} + +add_help_text mspm0_start_bootloader "Ask explicitly for bootloader startup" + +# MSPM0 requires board level NRST reset to be toggled for +# Factory reset operations to function. +# However this cannot be the default configuration as this +# prevents reset init reset halt to function properly +# since the Debug Subsystem (debugss) logic or coresight +# seems impacted by nRST. +# This can be overridden in board file as required. +# +# mspm0_board_reset: Board level reset +proc mspm0_board_reset {} { + set user_reset_config [reset_config] + reset_config srst_only + set errno [catch {reset}] + eval reset_config $user_reset_config + if {$errno} {error} +} + +add_help_text mspm0_board_reset "Request a board level reset" + +# If the flash is empty or the device is already in low-power state, then +# debug access is not available. to handle this, explicitly control power ap +# to provide access. Refer to Technical Reference Manual for further info. +proc _mspm0_enable_low_power_mode { } { + # PWR_AP::DPREC <= FRCACT(3)=1, RST_CTL(14:16)=1, IHIB_SLP(20)=1 + $::_CHIPNAME.dap apreg 4 0x00 0x104008 + # PWR_AP::SPREC <= SYSRST=1 + $::_CHIPNAME.dap apreg 4 0xF0 0x01 + # PWR_AP::DPREC <= FRCACT(3)=1, IHIB_SLP(20)=1 + $::_CHIPNAME.dap apreg 4 0x00 0x100008 +} + +$_TARGETNAME configure -event examine-start { _mspm0_enable_low_power_mode } +$_TARGETNAME configure -work-area-phys $_WORKAREABASE -work-area-size $_WORKAREASIZE -work-area-backup 0 + +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME.main mspm0 0 0 0 0 $_TARGETNAME +flash bank $_FLASHNAME.nonmain mspm0 0x41c00000 0 0 0 $_TARGETNAME +flash bank $_FLASHNAME.data mspm0 0x41d00000 0 0 0 $_TARGETNAME + +cortex_m reset_config sysresetreq