am_hal_tpiu.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. //*****************************************************************************
  2. //
  3. // am_hal_tpiu.c
  4. //! @file
  5. //!
  6. //! @brief Support functions for the ARM TPIU module
  7. //!
  8. //! Provides support functions for configuring the ARM TPIU module
  9. //!
  10. //! @addtogroup tpiu2 Trace Port Interface Unit (TPIU)
  11. //! @ingroup apollo2hal
  12. //! @{
  13. //
  14. //*****************************************************************************
  15. //*****************************************************************************
  16. //
  17. // Copyright (c) 2017, Ambiq Micro
  18. // All rights reserved.
  19. //
  20. // Redistribution and use in source and binary forms, with or without
  21. // modification, are permitted provided that the following conditions are met:
  22. //
  23. // 1. Redistributions of source code must retain the above copyright notice,
  24. // this list of conditions and the following disclaimer.
  25. //
  26. // 2. Redistributions in binary form must reproduce the above copyright
  27. // notice, this list of conditions and the following disclaimer in the
  28. // documentation and/or other materials provided with the distribution.
  29. //
  30. // 3. Neither the name of the copyright holder nor the names of its
  31. // contributors may be used to endorse or promote products derived from this
  32. // software without specific prior written permission.
  33. //
  34. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  35. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  36. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  37. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  38. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  39. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  40. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  41. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  42. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  43. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  44. // POSSIBILITY OF SUCH DAMAGE.
  45. //
  46. // This is part of revision 1.2.11 of the AmbiqSuite Development Package.
  47. //
  48. //*****************************************************************************
  49. #include <stdint.h>
  50. #include <stdbool.h>
  51. #include "am_mcu_apollo.h"
  52. //*****************************************************************************
  53. //
  54. //! @brief Enable the clock to the TPIU module.
  55. //!
  56. //! This function enables the clock to the TPIU module.
  57. //!
  58. //! @return None.
  59. //
  60. //*****************************************************************************
  61. void
  62. am_hal_tpiu_clock_enable(void)
  63. {
  64. //
  65. // Enable the TPIU clock
  66. //
  67. AM_REG(MCUCTRL, TPIUCTRL) |= AM_REG_MCUCTRL_TPIUCTRL_ENABLE_M;
  68. }
  69. //*****************************************************************************
  70. //
  71. //! @brief Disable the clock to the TPIU module.
  72. //!
  73. //! This function disables the clock to the TPIU module.
  74. //!
  75. //! @return None.
  76. //
  77. //*****************************************************************************
  78. void
  79. am_hal_tpiu_clock_disable(void)
  80. {
  81. //
  82. // Disable the TPIU clock
  83. //
  84. AM_REG(MCUCTRL, TPIUCTRL) &= ~AM_REG_MCUCTRL_TPIUCTRL_ENABLE_M;
  85. }
  86. //*****************************************************************************
  87. //
  88. //! @brief Set the output port width of the TPIU
  89. //!
  90. //! @param ui32PortWidth - The desired port width (in bits)
  91. //!
  92. //! This function uses the TPIU_CSPSR register to set the desired output port
  93. //! width of the TPIU.
  94. //!
  95. //! @return None.
  96. //
  97. //*****************************************************************************
  98. void
  99. am_hal_tpiu_port_width_set(uint32_t ui32PortWidth)
  100. {
  101. AM_REG(TPIU, CSPSR) = 1 << (ui32PortWidth - 1);
  102. }
  103. //*****************************************************************************
  104. //
  105. //! @brief Read the supported_output port width of the TPIU
  106. //!
  107. //! This function uses the \e TPIU_SSPSR register to set the supported output
  108. //! port widths of the TPIU.
  109. //!
  110. //! @return Current width of the TPIU output port
  111. //
  112. //*****************************************************************************
  113. uint32_t
  114. am_hal_tpiu_supported_port_width_get(void)
  115. {
  116. uint32_t i, ui32WidthValue;
  117. //
  118. // Read the supported width register.
  119. //
  120. ui32WidthValue = AM_REG(TPIU, SSPSR);
  121. //
  122. // The register value is encoded in a one-hot format, so the position of
  123. // the single set bit determines the actual width of the port.
  124. //
  125. for (i = 1; i < 32; i++)
  126. {
  127. //
  128. // Check each bit for a '1'. When we find it, our current loop index
  129. // will be equal to the port width.
  130. //
  131. if (ui32WidthValue == (0x1 << (i - 1)))
  132. {
  133. return i;
  134. }
  135. }
  136. //
  137. // We should never get here, but if we do, just return the smallest
  138. // possible value for a supported trace port width.
  139. //
  140. return 1;
  141. }
  142. //*****************************************************************************
  143. //
  144. //! @brief Read the output port width of the TPIU
  145. //!
  146. //! This function uses the \e TPIU_CSPSR register to set the desired output
  147. //! port width of the TPIU.
  148. //!
  149. //! @return Current width of the TPIU output port
  150. //
  151. //*****************************************************************************
  152. uint32_t
  153. am_hal_tpiu_port_width_get(void)
  154. {
  155. uint32_t ui32Temp;
  156. uint32_t ui32Width;
  157. ui32Width = 1;
  158. ui32Temp = AM_REG(TPIU, CSPSR);
  159. while ( !(ui32Temp & 1) )
  160. {
  161. ui32Temp = ui32Temp >> 1;
  162. ui32Width++;
  163. if (ui32Width > 32)
  164. {
  165. ui32Width = 0;
  166. break;
  167. }
  168. }
  169. //
  170. // Current width of the TPIU output port.
  171. //
  172. return ui32Width;
  173. }
  174. //*****************************************************************************
  175. //
  176. //! @brief Configure the TPIU based on the values in the configuration struct.
  177. //!
  178. //! @param psConfig - pointer to an am_hal_tpiu_config_t structure containing
  179. //! the desired configuration information.
  180. //!
  181. //! This function reads the provided configuration structure, and sets the
  182. //! relevant TPIU registers to achieve the desired configuration.
  183. //!
  184. //! @return None.
  185. //
  186. //*****************************************************************************
  187. void
  188. am_hal_tpiu_configure(am_hal_tpiu_config_t *psConfig)
  189. {
  190. //
  191. // Set the clock freq in the MCUCTRL register.
  192. //
  193. AM_REG(MCUCTRL, TPIUCTRL) |= psConfig->ui32TraceClkIn;
  194. //
  195. // Set the desired protocol.
  196. //
  197. AM_REG(TPIU, SPPR) = psConfig->ui32PinProtocol;
  198. //
  199. // Set the parallel port width. This may be redundant if the user has
  200. // selected a serial protocol, but we'll set it anyway.
  201. //
  202. AM_REG(TPIU, CSPSR) = (1 << (psConfig->ui32ParallelPortSize - 1));
  203. //
  204. // Set the clock prescaler.
  205. //
  206. AM_REG(TPIU, ACPR) = psConfig->ui32ClockPrescaler;
  207. }
  208. //*****************************************************************************
  209. //
  210. //! @brief Enables the TPIU
  211. //!
  212. //! This function enables the ARM TPIU by setting the TPIU registers and then
  213. //! enabling the TPIU clock source in MCU control register.
  214. //!
  215. //! @param psConfig - structure for configuration.
  216. //! If ui32SetItmBaud, the other structure members are used to set the
  217. //! TPIU configuration.
  218. //! But for simplicity, ui32SetItmBaud can be set to one of the
  219. //! following, in which case all other structure members are ignored.
  220. //! In this case, the given BAUD rate is based on a div-by-8 HFRC clock.
  221. //! AM_HAL_TPIU_BAUD_57600
  222. //! AM_HAL_TPIU_BAUD_115200
  223. //! AM_HAL_TPIU_BAUD_230400
  224. //! AM_HAL_TPIU_BAUD_460800
  225. //! AM_HAL_TPIU_BAUD_500000
  226. //! AM_HAL_TPIU_BAUD_1M
  227. //!
  228. //! @return None.
  229. //
  230. //*****************************************************************************
  231. void
  232. am_hal_tpiu_enable(am_hal_tpiu_config_t *psConfig)
  233. {
  234. uint32_t ui32HFRC, ui32SWOscaler, ui32ITMbitrate;
  235. ui32ITMbitrate = psConfig->ui32SetItmBaud;
  236. //
  237. // TPIU formatter & flush control register.
  238. //
  239. AM_REG(TPIU, FFCR) = 0;
  240. if ( ui32ITMbitrate )
  241. {
  242. //
  243. // Set the Current Parallel Port Size (note - only 1 bit can be set).
  244. //
  245. AM_REG(TPIU, CSPSR) = AM_REG_TPIU_CSPSR_CWIDTH_1BIT;
  246. //
  247. // Use some default assumptions to set the ITM frequency.
  248. //
  249. if ( (ui32ITMbitrate < AM_HAL_TPIU_BAUD_57600 ) ||
  250. (ui32ITMbitrate > AM_HAL_TPIU_BAUD_2M ) )
  251. {
  252. ui32ITMbitrate = AM_HAL_TPIU_BAUD_DEFAULT;
  253. }
  254. //
  255. // Get the current HFRC frequency.
  256. //
  257. ui32HFRC = am_hal_clkgen_sysclk_get();
  258. //
  259. // Compute the SWO scaler value.
  260. //
  261. if ( ui32HFRC != 0xFFFFFFFF )
  262. {
  263. ui32SWOscaler = ((ui32HFRC / 8) / ui32ITMbitrate) - 1;
  264. }
  265. else
  266. {
  267. ui32SWOscaler = ( (AM_HAL_CLKGEN_FREQ_MAX_HZ / 8) /
  268. AM_HAL_TPIU_BAUD_DEFAULT ) - 1;
  269. }
  270. //
  271. // Set the scaler value.
  272. //
  273. AM_REG(TPIU, ACPR) = AM_REG_TPIU_ACPR_SWOSCALER(ui32SWOscaler);
  274. //
  275. // Set for UART mode
  276. //
  277. AM_REG(TPIU, SPPR) = AM_REG_TPIU_SPPR_TXMODE_UART;
  278. //
  279. // Make sure we are not in test mode (important for proper deep sleep
  280. // operation).
  281. //
  282. AM_REG(TPIU, ITCTRL) = AM_REG_TPIU_ITCTRL_MODE_NORMAL;
  283. //
  284. // Enable the TPIU clock source in MCU control.
  285. // Set TPIU clock for HFRC/8 (6 or 3 MHz) operation.
  286. //
  287. AM_REGn(MCUCTRL, 0, TPIUCTRL) =
  288. AM_REG_MCUCTRL_TPIUCTRL_CLKSEL_HFRC_DIV_8 |
  289. AM_REG_MCUCTRL_TPIUCTRL_ENABLE_EN;
  290. }
  291. else
  292. {
  293. //
  294. // Set the configuration according to the structure values.
  295. //
  296. //
  297. // Set the Asynchronous Clock Prescaler Register.
  298. //
  299. AM_REG(TPIU, ACPR) = psConfig->ui32ClockPrescaler;
  300. //
  301. // Set the Selected Pin Protocol Register.
  302. // e.g. AM_REG_TPIU_SPPR_TXMODE_UART
  303. //
  304. AM_REG(TPIU, SPPR) = psConfig->ui32PinProtocol;
  305. //
  306. // Set the Current Parallel Port Size (note - only 1 bit can be set).
  307. // This may be redundant if the user has selected a serial protocol,
  308. // but we'll set it anyway.
  309. //
  310. AM_REG(TPIU, CSPSR) = (1 << (psConfig->ui32ParallelPortSize - 1));
  311. //
  312. // Set the clock freq in the MCUCTRL register.
  313. //
  314. AM_REG(MCUCTRL, TPIUCTRL) |= psConfig->ui32TraceClkIn;
  315. }
  316. //
  317. // Wait for 50us for the data to flush out.
  318. //
  319. am_hal_flash_delay(FLASH_CYCLES_US(50));
  320. }
  321. //*****************************************************************************
  322. //
  323. //! @brief Disables the TPIU
  324. //!
  325. //! This function disables the ARM TPIU by disabling the TPIU clock source
  326. //! in MCU control register.
  327. //!
  328. //! @return None.
  329. //
  330. //*****************************************************************************
  331. void
  332. am_hal_tpiu_disable(void)
  333. {
  334. //
  335. // Disable the TPIU clock source in MCU control.
  336. //
  337. AM_REG(MCUCTRL, TPIUCTRL) = AM_REG_MCUCTRL_TPIUCTRL_CLKSEL_0MHz |
  338. AM_REG_MCUCTRL_TPIUCTRL_ENABLE_DIS;
  339. }
  340. //*****************************************************************************
  341. //
  342. // End Doxygen group.
  343. //! @}
  344. //
  345. //*****************************************************************************