1 /***************************************************************************//**
2  * @file
3  * @brief Debug (DBG) Peripheral API
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
7  *******************************************************************************
8  *
9  * SPDX-License-Identifier: Zlib
10  *
11  * The licensor of this software is Silicon Laboratories Inc.
12  *
13  * This software is provided 'as-is', without any express or implied
14  * warranty. In no event will the authors be held liable for any damages
15  * arising from the use of this software.
16  *
17  * Permission is granted to anyone to use this software for any purpose,
18  * including commercial applications, and to alter it and redistribute it
19  * freely, subject to the following restrictions:
20  *
21  * 1. The origin of this software must not be misrepresented; you must not
22  *    claim that you wrote the original software. If you use this software
23  *    in a product, an acknowledgment in the product documentation would be
24  *    appreciated but is not required.
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  * 3. This notice may not be removed or altered from any source distribution.
28  *
29  ******************************************************************************/
30 
31 #include "em_dbg.h"
32 
33 #if defined(CoreDebug_DHCSR_C_DEBUGEN_Msk)
34 
35 #include "sl_assert.h"
36 #include "em_cmu.h"
37 #include "em_gpio.h"
38 #include "em_msc.h"
39 #if defined(_SILICON_LABS_32B_SERIES_2)
40 #include "em_se.h"
41 #endif
42 
43 /***************************************************************************//**
44  * @addtogroup dbg DBG - Debug
45  * @brief Debug (DBG) Peripheral API
46  * @details
47  *  This module contains functions to control the DBG peripheral of Silicon
48  *  Labs 32-bit MCUs and SoCs. The Debug Interface is used to program and debug
49  *  Silicon Labs devices.
50  * @{
51  ******************************************************************************/
52 
53 /*******************************************************************************
54  **************************   GLOBAL FUNCTIONS   *******************************
55  ******************************************************************************/
56 
57 #if defined(GPIO_ROUTE_SWOPEN) || defined(GPIO_ROUTEPEN_SWVPEN) \
58   || defined(GPIO_TRACEROUTEPEN_SWVPEN)
59 /***************************************************************************//**
60  * @brief
61  *   Enable Serial Wire Output (SWO) pin.
62  *
63  * @details
64  *   The SWO pin (sometimes denoted SWV, serial wire viewer) allows for
65  *   miscellaneous output to be passed from the Cortex-M3 debug trace module to
66  *   an external debug probe. By default, the debug trace module and pin output
67  *   may be disabled.
68  *
69  *   Since the SWO pin is only useful when using a debugger, a suggested use
70  *   of this function during startup may be:
71  * @verbatim
72  * if (DBG_Connected())
73  * {
74  * DBG_SWOEnable(1);
75  * }
76  * @endverbatim
77  *   By checking if the debugger is attached, a setup leading to a higher energy
78  *   consumption when the debugger is attached can be avoided when not using
79  *   a debugger.
80  *
81  *   Another alternative may be to set the debugger tool chain to configure
82  *   the required setup (similar to the content of this function) by some
83  *   sort of toolchain scripting during its attach/reset procedure. In that
84  *   case, the above suggested code for enabling the SWO pin is not required
85  *   in the application.
86  *
87  * @param[in] location
88  *   A pin location used for SWO pin on the application in use.
89  ******************************************************************************/
DBG_SWOEnable(unsigned int location)90 void DBG_SWOEnable(unsigned int location)
91 {
92   int port;
93   int pin;
94 
95 #if defined(GPIO_SWV_PORT)
96 
97   port = GPIO_SWV_PORT;
98   pin = GPIO_SWV_PIN;
99 
100 #else
101   EFM_ASSERT(location < AFCHANLOC_MAX);
102   #if defined (AF_DBG_SWO_PORT)
103   port = AF_DBG_SWO_PORT(location);
104   pin  = AF_DBG_SWO_PIN(location);
105   #elif defined (AF_DBG_SWV_PORT)
106   port = AF_DBG_SWV_PORT(location);
107   pin  = AF_DBG_SWV_PIN(location);
108 
109   #else
110   #warning "AF debug port is not defined."
111   #endif
112 #endif
113 
114   /* Port/pin location not defined for the device. */
115   if ((pin < 0) || (port < 0)) {
116     EFM_ASSERT(0);
117     return;
118   }
119 
120   /* Ensure that the auxiliary clock going to the Cortex debug trace module is enabled. */
121 #if !defined(_SILICON_LABS_32B_SERIES_2)
122   CMU_OscillatorEnable(cmuOsc_AUXHFRCO, true, false);
123 #endif
124 
125   /* Set the selected pin location for the SWO pin and enable it. */
126   GPIO_DbgLocationSet(location);
127   GPIO_DbgSWOEnable(true);
128 
129   /* Configure the SWO pin for output. */
130   GPIO_PinModeSet((GPIO_Port_TypeDef)port, pin, gpioModePushPull, 0);
131 }
132 #endif
133 
134 #if defined(LOCKBITS_BASE) && !defined(_EFM32_GECKO_FAMILY)
135 
136 /***************************************************************************//**
137  * @brief
138  *   Disable debug access.
139  *
140  * @cond DOXYDOC_S2_DEVICE
141  * @details
142  *   SE interface is used to disable debug access. By choosing
143  *   @ref dbgLockModePermanent, debug access is blocked permanently. SE disables
144  *   the device erase command and thereafter disables debug access.
145  * @endcond
146  * @cond DOXYDOC_P2_DEVICE
147  * @
148  * @details
149  *   Debug access is blocked using debug lock word. On series 1 devices,
150  *   if @ref dbgLockModePermanent is chosen, debug access is blocked
151  *   permanently using AAP lock word.
152  * @endcond
153  * @param[in] lockMode
154  *   Debug lock mode to be used.
155  *
156  * @cond !DOXYDOC_P1_DEVICE
157  * @warning
158  *   If @ref dbgLockModePermanent is chosen as the lock mode, the debug port
159  *   will be closed permanently and is irreversible.
160  * @endcond
161  ******************************************************************************/
DBG_DisableDebugAccess(DBG_LockMode_TypeDef lockMode)162 void DBG_DisableDebugAccess(DBG_LockMode_TypeDef lockMode)
163 {
164 #if defined(SEMAILBOX_PRESENT)
165   if (lockMode == dbgLockModeAllowErase) {
166     SE_debugLockApply();
167   } else if (lockMode == dbgLockModePermanent) {
168     SE_deviceEraseDisable();
169     SE_debugLockApply();
170   } else {
171     /* Invalid input */
172     EFM_ASSERT(0);
173   }
174 #else
175 #if defined(_SILICON_LABS_32B_SERIES_0)
176   if (lockMode != dbgLockModeAllowErase) {
177     EFM_ASSERT(0);
178   }
179 #else
180   if ((lockMode != dbgLockModeAllowErase) && (lockMode != dbgLockModePermanent)) {
181     EFM_ASSERT(0);
182   }
183 #endif
184 
185   bool wasLocked;
186   uint32_t lockWord = 0x0;
187   wasLocked = ((MSC->LOCK & _MSC_LOCK_MASK) != 0U);
188   MSC_Init();
189 
190   uint32_t *dlw = (uint32_t*)(LOCKBITS_BASE + (127 * 4));
191 
192   if (*dlw == 0xFFFFFFFF) {
193     MSC_WriteWord(dlw, &lockWord, sizeof(lockWord));
194   }
195 #if !defined(_SILICON_LABS_32B_SERIES_0)
196   uint32_t *alw = (uint32_t*)(LOCKBITS_BASE + (124 * 4));
197 
198   if (lockMode == dbgLockModePermanent) {
199     if (*alw == 0xFFFFFFFF) {
200       MSC_WriteWord(alw, &lockWord, sizeof(lockWord));
201     }
202   }
203 #endif
204 
205   if (wasLocked) {
206     MSC_Deinit();
207   }
208 #endif
209 }
210 
211 #endif /* defined(LOCKBITS_BASE) && !defined(_EFM32_GECKO_FAMILY) */
212 
213 /** @} (end addtogroup dbg) */
214 #endif /* defined( CoreDebug_DHCSR_C_DEBUGEN_Msk ) */
215