| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- /***********************************************************************
- * SEGGER Microcontroller GmbH *
- * The Embedded Experts *
- ************************************************************************
- * *
- * (c) SEGGER Microcontroller GmbH *
- * All rights reserved *
- * www.segger.com *
- * *
- ************************************************************************
- * *
- ************************************************************************
- * *
- * *
- * Licensing terms *
- * *
- * The use in source and binary forms, with or without modification, *
- * is permitted for internal use only. The redistribution to any *
- * third party is prohibited. *
- * *
- * *
- * THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER "AS IS" AND ANY *
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE *
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR *
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE *
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, *
- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY *
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
- * DAMAGE. *
- * *
- ************************************************************************
- -------------------------- END-OF-HEADER -----------------------------
- Purpose: Implementation of device specific handling for
- ST STM32U5xxxx devices
- Literature:
- [1] J-Link User Guide
- [2] ST RM0456 (STM32U5 Reference manual)
- Additional information:
- [3] ...
- */
- /*********************************************************************
- *
- * Constants, fixed
- *
- **********************************************************************
- */
- //
- // Registers
- //
- __constant U32 _DHCSR_ADDR = 0xE000EDF0;
- __constant U32 _DEMCR_ADDR = 0xE000EDFC; // Debug Exception and Monitor Control Register
- __constant U32 _AIRCR_ADDR = 0xE000ED0C; // Application Interrupt and Reset Control Register
- __constant U32 _CPUID_ADDR = 0xE000ED00;
- //
- // Bits
- //
- __constant U32 _DP_CTRL_STAT_BIT_DBGPWRUPREQ = (1 << 30);
- __constant U32 _DP_CTRL_STAT_BIT_SYSPWRUPREQ = (1 << 28);
- __constant U32 _DP_CTRL_STAT_BIT_STICKYERR = (1 << 5);
- //
- // Shifts
- //
- __constant U32 _BIT_S_HALTED = (1 << 17);
- /*********************************************************************
- *
- * Constants, configurable (might differ between STM32 devices)
- *
- **********************************************************************
- */
- //
- // Registers
- //
- __constant U32 _FLASH_BASE = 0x50022000;
- __constant U32 _FLASH_BASE_NS = 0x40022000;
- __constant U32 _FLASH_NSKEYR = _FLASH_BASE_NS + 0x08;
- __constant U32 _FLASH_OPTKEYR = _FLASH_BASE_NS + 0x10;
- __constant U32 _FLASH_NSSR = _FLASH_BASE_NS + 0x20;
- __constant U32 _FLASH_NSCR = _FLASH_BASE_NS + 0x28;
- __constant U32 _FLASH_OPTR = _FLASH_BASE_NS + 0x40;
- //
- // Shifts & Bits & Masks ...
- //
- // FLASH_SR
- //
- __constant U32 _BIT_BSY = 16;
- __constant U32 _CLEAR_ERR_SR = 0x000020F8;
- //
- // FLASH_CR
- //
- __constant U32 _BIT_OPTSTRT = (1 << 17);
- __constant U32 _BIT_OBLLAUNCH = (1 << 27); // Launch option byte loading
- __constant U32 _BIT_OPTLOCK = (1 << 30);
- __constant U32 _BIT_LOCK = (1 << 31);
- //
- // FLASH_OPTR
- //
- __constant U32 _RDP_LVL_0 = (0xAA << 0);
- __constant U32 _RDP_LVL_05 = (0x55 << 0);
- __constant U32 _RDP_LVL_1 = (0xBB << 0);
- __constant U32 _BIT_NSWBOOT0 = (1 << 26);
- __constant U32 _BIT_NBOOT0 = (1 << 27);
- __constant U32 _BIT_TZEN = (1 << 31);
- __constant U32 _MASK_RDP = 0x000000FF;
- __constant U32 _MASK_BOOT = 0x0C000000;
- __constant U32 _OPTR_FACT_VAL = 0x1FEFF8AA;
- //
- // Keys
- //
- __constant U32 _FLASH_KEY1 = 0x45670123;
- __constant U32 _FLASH_KEY2 = 0xCDEF89AB;
- __constant U32 _OPT_KEY1 = 0x08192A3B;
- __constant U32 _OPT_KEY2 = 0x4C5D6E7F;
- //
- // Misc
- //
- __constant U32 _DEF_BUSY_TIMEOUT = 500;
- /*********************************************************************
- *
- * Static code
- *
- **********************************************************************
- */
- /*********************************************************************
- *
- * _ConfigureAP()
- *
- * Function description
- * Configures selected AP for debugging.
- */
- static int _ConfigureAP(U32 Index) {
- U32 v;
- int r;
- //
- // Select AP and bank to use
- //
- v = 0
- | (0 << 4) // Select bank 0 (this is default for most casese).
- | (Index << 24) // Select AP[Index] (AHB-AP)
- ;
- JLINK_CORESIGHT_WriteDP(JLINK_CORESIGHT_DP_REG_SELECT, v);
- //
- // Initialize DAP for debug use.
- //
- v = (2 << 0) // Access size: word
- | (0 << 4) // NO Auto-increment
- | (1 << 25) // Priviledged access
- | (0 << 30) // Secure transfer
- ;
- r = JLINK_CORESIGHT_WriteAP(JLINK_CORESIGHT_AP_REG_CTRL, v);
- if (r < 0) {
- JLINK_SYS_Report(" Error: Failed to configure AP.");
- return -1;
- }
- return 0;
- }
- /*********************************************************************
- *
- * _InitDAP()
- *
- * Function description
- * Initializes DAP, so JLINK_CORESIGHT_ functions can be used.
- */
- static int _InitDAP(void) {
- U32 v;
- int r;
- int t;
- //
- // Clear sticky error flags and power up DAP
- //
- v = _DP_CTRL_STAT_BIT_DBGPWRUPREQ | _DP_CTRL_STAT_BIT_SYSPWRUPREQ;
- if (JLINK_ActiveTIF == JLINK_TIF_JTAG) {
- v |= _DP_CTRL_STAT_BIT_STICKYERR;
- } else {
- JLINK_CORESIGHT_WriteDP(JLINK_CORESIGHT_DP_REG_ABORT, 0x1E);
- }
- JLINK_CORESIGHT_WriteDP(JLINK_CORESIGHT_DP_REG_CTRL_STAT, v);
- //
- // Wait for power up DAP complete
- //
- r = -1;
- t = JLINK_GetTime() + _DEF_BUSY_TIMEOUT;
- do {
- r = JLINK_CORESIGHT_ReadDP(JLINK_CORESIGHT_DP_REG_CTRL_STAT);
- if (r == -1) { // Any error occurred while reading from the DP, we are done
- break;
- }
- v = r;
- if (v & (0xF << 28)) { // CSYSPWRUPACK and CDBGPWRUPACK set, so both ports have been completely powered?
- r = 0;
- break;
- }
- if ((t - JLINK_GetTime()) <= 0) {
- break;
- }
- } while(1);
- if (r < 0) {
- JLINK_SYS_Report(" Error: Failed to initialized DAP.");
- return -1;
- }
- r = _ConfigureAP(0); // Finally configure the AP so we can use it.
- if (r < 0) {
- return -1;
- }
- return 0;
- }
- /*********************************************************************
- *
- * _WaitWhileBusy
- *
- * Function descripton
- * Wait until read value is not busy.
- *
- * Return value
- * 0 O.K.
- * < 0 Error
- * -1 Timeout reached
- * -2 Error reading/writing DAP
- */
- static int _WaitWhileBusy(U32 Addr, U32 Mask, U32 RefValue, U32 Timeout) {
- int r;
- int t;
- U32 Status;
- RefValue &= Mask;
- r = -1;
- //
- // Wait for operation to complete
- //
- t = JLINK_GetTime() + Timeout;
- do {
- r = JLINK_MEM_ReadU32(Addr);
- //
- // Check for error while reading/writing AP.
- // We do this because this function might be called after a reset,
- // e.g. from _WaitCPUHalted()
- //
- if (r == -1) { // Connection lost ? => Error.
- r = -2;
- break;
- }
- Status = r;
- if ((Status & Mask) == RefValue) { // Operation complete? => Done.
- r = 0;
- break;
- }
- if ((t - JLINK_GetTime()) < 0) { // Timeout reached? => Error.
- r = -1;
- break;
- }
- } while (1);
- return r;
- }
- /*********************************************************************
- *
- * _WaitWhileFlashBusy
- *
- * Function descripton
- * Wrapper for _WaitWhileBuys, to make Flash wait calls simpler.
- */
- static int _WaitWhileFlashBusy(U32 Timeout) {
- return _WaitWhileBusy(_FLASH_NSSR, _BIT_BSY, ~_BIT_BSY, Timeout);
- }
- /*********************************************************************
- *
- * _WaitCPUHalted
- *
- * Function description
- * Wait for DHCSR to signal that the CPU is halted.
- *
- * Return value
- * 0 O.K.
- * < 0 Error
- */
- static int _WaitCPUHalted(void) {
- int r;
- r = _WaitWhileBusy(_DHCSR_ADDR, _BIT_S_HALTED, _BIT_S_HALTED, _DEF_BUSY_TIMEOUT);
- if (r == -1) {
- JLINK_SYS_Report(" Timeout while waiting for CPU to halt.");
- } else if (r == -2) {
- JLINK_SYS_Report(" Error while checking CPU state.");
- }
- return r;
- }
- /*********************************************************************
- *
- * _Reset
- *
- * Function description
- * Reset and wait until CPU is halted.
- *
- * Return value
- * 0 O.K.
- * < 0 Error
- */
- static int _Reset(void) {
- int r;
- U32 v;
- U32 demcr;
- r = JLINK_MEM_ReadU32(_DHCSR_ADDR);
- if (r < 0) {
- return -1;
- }
- v = r;
- v &= 0x3F; // Mask out "debug" bits
- v |= (0xA05F << 16); // Debug key to make a write to the DHCSR a valid one
- v |= (1 << 1); // Halt the core
- v |= (1 << 0); // Enable debug functionalities of the core
- JLINK_MEM_WriteU32(_DHCSR_ADDR, v);
- demcr = JLINK_MEM_ReadU32(_DEMCR_ADDR);
- JLINK_MEM_WriteU32(_DEMCR_ADDR, demcr | (1 << 0)); // Set VC_CORERESET
- JLINK_MEM_WriteU32(_AIRCR_ADDR, 0x05FA0004); // SYSRESETREQ
- r = _WaitCPUHalted();
- if (r < 0) {
- return -1;
- }
- _InitDAP();
- return 0;
- }
- /*********************************************************************
- *
- * _UnlockOptionbytes
- *
- * Function description
- * Unlock the Flash registers and Optionbytes if not yet unlocked.
- *
- * Return value
- * 0 O.K.
- * < 0 Error
- */
- static void _UnlockOptionbytes(void) {
- U32 v;
- v = JLINK_MEM_ReadU32(_FLASH_NSCR);
- if (v & _BIT_LOCK) {
- JLINK_MEM_WriteU32(_FLASH_NSKEYR, _FLASH_KEY1);
- JLINK_MEM_WriteU32(_FLASH_NSKEYR, _FLASH_KEY2);
- }
- if (v & _BIT_OPTLOCK) {
- JLINK_MEM_WriteU32(_FLASH_OPTKEYR, _OPT_KEY1);
- JLINK_MEM_WriteU32(_FLASH_OPTKEYR, _OPT_KEY2);
- }
- }
- /*********************************************************************
- *
- * _ProgOptionbytes
- *
- * Function description
- * Triggers option byte programming and launching of the option bytes.
- *
- * Return value
- * 0 O.K.
- * < 0 Error
- */
- static int _ProgOptionbytes(void) {
- int r;
- U32 v;
- JLINK_MEM_WriteU32(_FLASH_NSSR, _CLEAR_ERR_SR); // Reset FLASH_SR error bits
- JLINK_MEM_WriteU32(_FLASH_NSCR, _BIT_OPTSTRT);
- r = _WaitWhileFlashBusy(30000); // Changing RDP might trigger a mass erase, so we have to give this some time.
- if (r < 0) {
- return r;
- }
- //
- // Set OBL_LAUNCH bit
- // After the OBL_LAUNCH has been set, the device is not responsive until reset,
- // so we wait some time and reconnect to the device
- //
- JLINK_MEM_WriteU32(_FLASH_NSCR, _BIT_OBLLAUNCH);
- JLINK_SYS_Sleep(200); // Give OBL_LAUNCH some time
- r = _InitDAP(); // CPU has to be reconnected after reset!
- return r;
- }
- /*********************************************************************
- *
- * _DisableTZENIfActive
- *
- * Function description
- * Disable TrustZone on the device if active.
- *
- * Return value
- * 0 O.K.
- * < 0 Error
- */
- static int _DisableTZENIfActive(void) {
- int r;
- U32 v;
- U32 vOPTR;
- vOPTR = JLINK_MEM_ReadU32(_FLASH_OPTR);
- if ((vOPTR & _BIT_TZEN) == 0) { // TZEN not set? => Nothing to do.
- JLINK_SYS_Report(" TrustZone not enabled (TZEN == 0).");
- return 0;
- }
- JLINK_SYS_Report(" TrustZone enabled (TZEN == 1).");
- JLINK_SYS_Report(" Resetting OPTR to factory value...");
- //
- // Reset device to be in a defined state.
- //
- r = _Reset();
- if (r < 0) {
- return -1;
- }
- //
- // Check RDP
- //
- v = vOPTR & _MASK_RDP;
- if ((v == _RDP_LVL_0) || (v == _RDP_LVL_05)) {
- //
- // Set special boot mode if TZEN is active, but RDP is not Level 1.
- // We do this, because when TZEN == 1, we are only able to read/write the flash registers while
- // the CPU is executing non-secure code.
- // By setting the boot mode while TZEN is set, we force the device to boot RSS, which is then
- // executing non-secure code, which enables us to regress from RDP level 1.
- //
- vOPTR &= ~(_BIT_NSWBOOT0 | _BIT_NBOOT0); // Set bootmode to BTL
- vOPTR &= ~_MASK_RDP; // Mask out RDP
- vOPTR |= _RDP_LVL_1; // Set RDP level 1
- _UnlockOptionbytes();
- JLINK_MEM_WriteU32(_FLASH_OPTR, vOPTR);
- r = _ProgOptionbytes();
- if (r < 0) {
- return -1;
- }
- }
- //
- // Reset OPTR to factory value
- //
- _UnlockOptionbytes();
- JLINK_MEM_WriteU32(_FLASH_OPTR, _OPTR_FACT_VAL);
- r = _ProgOptionbytes();
- if (r < 0) {
- return -1;
- }
- v = JLINK_MEM_ReadU32(_FLASH_OPTR);
- if (v & _BIT_TZEN) {
- JLINK_SYS_Report(" TrustZone still enabled after disable sequence.");
- return -1;
- }
- r = _Reset();
- if (r < 0) {
- return -1;
- }
- JLINK_SYS_Report(" TrustZone disabled successfully.");
- return 0;
- }
- /*********************************************************************
- *
- * Global functions
- *
- **********************************************************************
- */
- /*********************************************************************
- *
- * SetupTarget()
- *
- * Function description
- * If present, called after InitTarget() and after general debug connect sequence
- * has been performed by J-Link. Usually used for more high-level CPU debug setup
- * like writing certain memory locations, initializing PLL for faster download etc.
- *
- * Return value
- * >= 0: O.K.
- * < 0: Error
- *
- * Notes
- * (1) Does not replace any DLL functionality but extends it.
- * (2) May use MEM_ API functions
- */
- int SetupTarget(void) {
- int r;
- r = _DisableTZENIfActive();
- if (r < 0) {
- JLINK_SYS_Report(" Disabling TrustZone failed.");
- return -1;
- }
- return 0;
- }
- /*************************** end of file ****************************/
|