am_hal_sysctrl.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. //*****************************************************************************
  2. //
  3. // am_hal_sysctrl.c
  4. //! @file
  5. //!
  6. //! @brief Functions for interfacing with the M4F system control registers
  7. //!
  8. //! @addtogroup sysctrl2 System Control (SYSCTRL)
  9. //! @ingroup apollo2hal
  10. //! @{
  11. //
  12. //*****************************************************************************
  13. //*****************************************************************************
  14. //
  15. // Copyright (c) 2017, Ambiq Micro
  16. // All rights reserved.
  17. //
  18. // Redistribution and use in source and binary forms, with or without
  19. // modification, are permitted provided that the following conditions are met:
  20. //
  21. // 1. Redistributions of source code must retain the above copyright notice,
  22. // this list of conditions and the following disclaimer.
  23. //
  24. // 2. Redistributions in binary form must reproduce the above copyright
  25. // notice, this list of conditions and the following disclaimer in the
  26. // documentation and/or other materials provided with the distribution.
  27. //
  28. // 3. Neither the name of the copyright holder nor the names of its
  29. // contributors may be used to endorse or promote products derived from this
  30. // software without specific prior written permission.
  31. //
  32. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  33. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  34. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  35. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  36. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  37. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  38. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  39. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  40. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  41. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  42. // POSSIBILITY OF SUCH DAMAGE.
  43. //
  44. // This is part of revision 1.2.11 of the AmbiqSuite Development Package.
  45. //
  46. //*****************************************************************************
  47. #include <stdint.h>
  48. #include <stdbool.h>
  49. #include "am_mcu_apollo.h"
  50. //*****************************************************************************
  51. //
  52. // Local macro constants
  53. //
  54. //*****************************************************************************
  55. //
  56. // Define ZX workaround values.
  57. // These values are defined by the factory.
  58. //
  59. #define COREZXVALUE 0x07
  60. #define MEMZXVALUE 0x07
  61. //
  62. // Define values for g_ui32CoreBuck, which indicates which timer carries
  63. // the signal for the CORE Buck, and which also implies that the other timer
  64. // carries the signal for the MEM buck.
  65. //
  66. #define COREBUCK_TIMERA 1 // Core buck signal comes in on timer A
  67. #define COREBUCK_TIMERB 2 // Core buck signal comes in on timer B
  68. //
  69. // Define the bit values for static function g_buckZX_chk;
  70. //
  71. #define CHKBUCKZX_BUCKS 0x01 // The bucks are enabled
  72. #define CHKBUCKZX_REV 0x02 // This chip rev needs the workaround
  73. #define CHKBUCKZX_TIMER 0x04 // A valid timer has been allocated
  74. #define CHKBUCKZX_DEVEN 0x08 // Devices are powered up and enabled
  75. //*****************************************************************************
  76. //
  77. // Prototypes
  78. //
  79. //*****************************************************************************
  80. static void am_hal_sysctrl_buckA_ctimer_isr(void);
  81. static void am_hal_sysctrl_buckB_ctimer_isr(void);
  82. //*****************************************************************************
  83. //
  84. // Globals
  85. //
  86. //*****************************************************************************
  87. static volatile uint32_t g_ui32BuckTimer = 0;
  88. static volatile uint32_t g_ui32BuckInputs = 0;
  89. static volatile bool g_bBuckRestoreComplete = false;
  90. static volatile bool g_bBuckTimed = false;
  91. static uint32_t g_ui32SaveCoreBuckZX, g_ui32SaveMemBuckZX;
  92. static uint32_t g_buckZX_chk = 0;
  93. static volatile uint32_t g_ui32CoreBuck;
  94. //
  95. // Timer configuration for BUCK inputs.
  96. //
  97. static const am_hal_ctimer_config_t g_sBuckTimer =
  98. {
  99. // Don't link timers.
  100. 0,
  101. // Set up Timer0A.
  102. (AM_HAL_CTIMER_FN_ONCE |
  103. AM_HAL_CTIMER_INT_ENABLE |
  104. AM_HAL_CTIMER_BUCK),
  105. // Set up Timer0B.
  106. (AM_HAL_CTIMER_FN_ONCE |
  107. AM_HAL_CTIMER_INT_ENABLE |
  108. AM_HAL_CTIMER_BUCK),
  109. };
  110. //*****************************************************************************
  111. //
  112. // Determine if we need to do the zero cross workaround on this device.
  113. // Three criteria are used. All three must be true.
  114. // 1. Are the bucks enabled?
  115. // 2. Is the chip rev appropriate for the workaround?
  116. // 3. Has a timer been allocated to do the workaround?
  117. // 4. Are certain peripherals powered up?
  118. //
  119. // Saves the bitmask to the global g_buckZX_chk.
  120. // Bitmask bits are defined as: CHKBUCKZX_BUCKS, CHKBUCKZX_REV, CHKBUCKZX_TIMER.
  121. //
  122. // Returns true if all criteria are met, false otherwise.
  123. // g_buckZX_chk can be probed to determine which criteria passed or failed.
  124. //
  125. //*****************************************************************************
  126. static bool
  127. buckZX_chk(void)
  128. {
  129. uint32_t ui32SupplySrc;
  130. //
  131. // Is this chip rev appropriate to do the workaround?
  132. //
  133. g_buckZX_chk = AM_BFM(MCUCTRL, CHIPREV, REVMAJ) == AM_REG_MCUCTRL_CHIPREV_REVMAJ_B ?
  134. CHKBUCKZX_REV : 0x0;
  135. //
  136. // Has a timer been configured to handle the workaround?
  137. //
  138. g_buckZX_chk |= ( g_ui32BuckTimer - 1 ) <= BUCK_TIMER_MAX ?
  139. CHKBUCKZX_TIMER : 0x0;
  140. //
  141. // Are either or both of the bucks actually enabled?
  142. //
  143. ui32SupplySrc = AM_REG(PWRCTRL, SUPPLYSRC);
  144. g_buckZX_chk |= (ui32SupplySrc &
  145. (AM_REG_PWRCTRL_SUPPLYSRC_COREBUCKEN_M |
  146. AM_REG_PWRCTRL_SUPPLYSRC_MEMBUCKEN_M) ) ?
  147. CHKBUCKZX_BUCKS : 0x0;
  148. //
  149. // Finally, if any peripheral is already powered up, we don't need to do the
  150. // ZX workaround because in this case the bucks remain in active mode.
  151. //
  152. ui32SupplySrc = AM_REG(PWRCTRL, DEVICEEN);
  153. g_buckZX_chk |= ( ui32SupplySrc &
  154. (AM_REG_PWRCTRL_DEVICEEN_PDM_M |
  155. AM_REG_PWRCTRL_DEVICEEN_UART1_M |
  156. AM_REG_PWRCTRL_DEVICEEN_UART0_M |
  157. AM_REG_PWRCTRL_DEVICEEN_IO_MASTER5_M |
  158. AM_REG_PWRCTRL_DEVICEEN_IO_MASTER4_M |
  159. AM_REG_PWRCTRL_DEVICEEN_IO_MASTER3_M |
  160. AM_REG_PWRCTRL_DEVICEEN_IO_MASTER2_M |
  161. AM_REG_PWRCTRL_DEVICEEN_IO_MASTER1_M |
  162. AM_REG_PWRCTRL_DEVICEEN_IO_MASTER0_M |
  163. AM_REG_PWRCTRL_DEVICEEN_IO_SLAVE_M) ) ?
  164. 0x0 : CHKBUCKZX_DEVEN;
  165. //
  166. // If all 4 criteria were met, we're good to do the workaround.
  167. //
  168. return ( g_buckZX_chk ==
  169. (CHKBUCKZX_BUCKS | CHKBUCKZX_REV |
  170. CHKBUCKZX_TIMER | CHKBUCKZX_DEVEN) ) ? true : false;
  171. }
  172. //*****************************************************************************
  173. //
  174. // Set the buck zero cross settings to the values given.
  175. //
  176. // ui32Flags, one or more of the following:
  177. // SETBUCKZX_USE_PROVIDED_SETTINGS - Use the values provided in the parameters
  178. // to set the trim value(s).
  179. // SETBUCKZX_USE_SAVED_SETTINGS - Use the values that were previously saved
  180. // to set the trim value(s).
  181. // SETBUCKZX_SAVE_CURR_SETTINGS - Save the current trim values before
  182. // setting the new ones.
  183. // SETBUCKZX_RESTORE_CORE_ONLY - Restore the Core trim and save the current
  184. // value of the core buck trim iff
  185. // SETBUCKZX_SAVE_CURR_SETTINGS is set.
  186. // SETBUCKZX_RESTORE_MEM_ONLY - Restore the Mem trim and save the current
  187. // value of the mem buck trim iff
  188. // SETBUCKZX_SAVE_CURR_SETTINGS is set.
  189. // SETBUCKZX_RESTORE_BOTH - Restore both buck trims and save the
  190. // current value of both iff
  191. // SETBUCKZX_SAVE_CURR_SETTINGS is set.
  192. //
  193. //*****************************************************************************
  194. #define SETBUCKZX_USE_PROVIDED_SETTINGS 0x01
  195. #define SETBUCKZX_USE_SAVED_SETTINGS 0x02
  196. #define SETBUCKZX_SAVE_CURR_SETTINGS 0x04
  197. #define SETBUCKZX_RESTORE_CORE_ONLY 0x10
  198. #define SETBUCKZX_RESTORE_MEM_ONLY 0x20
  199. #define SETBUCKZX_RESTORE_BOTH ( SETBUCKZX_RESTORE_CORE_ONLY | \
  200. SETBUCKZX_RESTORE_MEM_ONLY )
  201. static void
  202. setBuckZX(uint32_t ui32CoreBuckZX, uint32_t ui32MemBuckZX, uint32_t ui32Flags)
  203. {
  204. uint32_t ui32SaveCore, ui32SaveMem, ui32NewCore, ui32NewMem;
  205. bool bDoRestore = false;
  206. //
  207. // Begin critical section.
  208. //
  209. AM_CRITICAL_BEGIN_ASM
  210. //
  211. // Get the current zero cross trim values.
  212. //
  213. ui32SaveCore = AM_BFR(MCUCTRL, BUCK3, COREBUCKZXTRIM);
  214. ui32SaveMem = AM_BFR(MCUCTRL, BUCK3, MEMBUCKZXTRIM);
  215. //
  216. // Determine which values will be restored.
  217. //
  218. if ( ui32Flags & SETBUCKZX_USE_SAVED_SETTINGS )
  219. {
  220. //
  221. // Use saved settings
  222. //
  223. ui32NewCore = g_ui32SaveCoreBuckZX;
  224. ui32NewMem = g_ui32SaveMemBuckZX;
  225. bDoRestore = true;
  226. }
  227. else if ( ui32Flags & SETBUCKZX_USE_PROVIDED_SETTINGS )
  228. {
  229. //
  230. // Use settings provided in the call parameters
  231. //
  232. ui32NewCore = ui32CoreBuckZX;
  233. ui32NewMem = ui32MemBuckZX;
  234. bDoRestore = true;
  235. }
  236. //
  237. // Restore the buck Core and Mem trim registers.
  238. //
  239. if ( bDoRestore )
  240. {
  241. if ( ui32Flags & SETBUCKZX_RESTORE_CORE_ONLY )
  242. {
  243. AM_BFW(MCUCTRL, BUCK3, COREBUCKZXTRIM, ui32NewCore);
  244. }
  245. if ( ui32Flags & SETBUCKZX_RESTORE_MEM_ONLY )
  246. {
  247. AM_BFW(MCUCTRL, BUCK3, MEMBUCKZXTRIM, ui32NewMem);
  248. }
  249. }
  250. if ( ui32Flags & SETBUCKZX_SAVE_CURR_SETTINGS )
  251. {
  252. //
  253. // Save off the zero cross values as read on entry to the function.
  254. //
  255. if ( ui32Flags & SETBUCKZX_RESTORE_CORE_ONLY )
  256. {
  257. g_ui32SaveCoreBuckZX = ui32SaveCore;
  258. }
  259. if ( ui32Flags & SETBUCKZX_RESTORE_MEM_ONLY )
  260. {
  261. g_ui32SaveMemBuckZX = ui32SaveMem;
  262. }
  263. }
  264. //
  265. // Done with critical section.
  266. //
  267. AM_CRITICAL_END_ASM
  268. }
  269. //*****************************************************************************
  270. //
  271. //! @brief Place the core into sleep or deepsleep.
  272. //!
  273. //! @param bSleepDeep - False for Normal or True Deep sleep.
  274. //!
  275. //! This function puts the MCU to sleep or deepsleep depending on bSleepDeep.
  276. //!
  277. //! Valid values for bSleepDeep are:
  278. //!
  279. //! AM_HAL_SYSCTRL_SLEEP_NORMAL
  280. //! AM_HAL_SYSCTRL_SLEEP_DEEP
  281. //!
  282. //! @return None.
  283. //
  284. //*****************************************************************************
  285. void
  286. am_hal_sysctrl_sleep(bool bSleepDeep)
  287. {
  288. uint32_t ui32Critical;
  289. // uint32_t ui32DebugGpioSleep = g_ui32DebugGpioSleep - 1;
  290. bool bBuckZX_chk;
  291. volatile uint32_t ui32BuckTimer;
  292. //
  293. // Disable interrupts and save the previous interrupt state.
  294. //
  295. ui32Critical = am_hal_interrupt_master_disable();
  296. //
  297. // If the user selected DEEPSLEEP and the TPIU is off, attempt to enter
  298. // DEEP SLEEP.
  299. //
  300. if ((bSleepDeep == AM_HAL_SYSCTRL_SLEEP_DEEP) &&
  301. (AM_BFM(MCUCTRL, TPIUCTRL, ENABLE) == AM_REG_MCUCTRL_TPIUCTRL_ENABLE_DIS))
  302. {
  303. //
  304. // Prepare the core for deepsleep (write 1 to the DEEPSLEEP bit).
  305. //
  306. AM_BFW(SYSCTRL, SCR, SLEEPDEEP, 1);
  307. //
  308. // Check if special buck handling is needed
  309. //
  310. bBuckZX_chk = buckZX_chk();
  311. if ( bBuckZX_chk )
  312. {
  313. ui32BuckTimer = g_ui32BuckTimer - 1;
  314. //
  315. // Before going to sleep, clear the buck timers.
  316. // This will also handle the case where we're going back to
  317. // sleep before the buck sequence has even completed.
  318. //
  319. am_hal_ctimer_clear(ui32BuckTimer, AM_HAL_CTIMER_BOTH);
  320. //
  321. // Set CMPR0 of both timerA and timerB to the period value
  322. //
  323. #define TIMER_PERIOD_BUCKS 1
  324. am_hal_ctimer_period_set(ui32BuckTimer,
  325. AM_HAL_CTIMER_BOTH,
  326. TIMER_PERIOD_BUCKS |
  327. (TIMER_PERIOD_BUCKS << 16),
  328. 0);
  329. //
  330. // Disable bucks before going to sleep.
  331. //
  332. am_hal_pwrctrl_bucks_disable();
  333. }
  334. //
  335. // Execute the sleep instruction.
  336. //
  337. AM_ASM_WFI;
  338. //
  339. // Return from sleep
  340. //
  341. if ( bBuckZX_chk )
  342. {
  343. //
  344. // Adjust the core and mem trims
  345. //
  346. setBuckZX(COREZXVALUE, MEMZXVALUE,
  347. SETBUCKZX_USE_PROVIDED_SETTINGS |
  348. SETBUCKZX_RESTORE_BOTH );
  349. //
  350. // Delay for 2us before enabling bucks.
  351. //
  352. am_hal_flash_delay( FLASH_CYCLES_US(2) );
  353. //
  354. // Turn on the bucks
  355. //
  356. am_hal_pwrctrl_bucks_enable();
  357. //
  358. // Get the actual timer number
  359. //
  360. ui32BuckTimer = g_ui32BuckTimer - 1;
  361. //
  362. // Initialize the complete flag
  363. //
  364. g_bBuckRestoreComplete = false;
  365. //
  366. // Initialize the input flags
  367. //
  368. g_ui32BuckInputs = 0;
  369. //
  370. // Delay for 5us to make sure we're receiving clean buck signals.
  371. //
  372. am_hal_flash_delay( FLASH_CYCLES_US(5) );
  373. //
  374. // Start timers (set the enable bit, clear the clear bit)
  375. //
  376. am_hal_ctimer_start(ui32BuckTimer, AM_HAL_CTIMER_BOTH);
  377. }
  378. else
  379. {
  380. //
  381. // Since we're not doing anything, we're done, so set the done flag.
  382. //
  383. g_bBuckRestoreComplete = true;
  384. }
  385. }
  386. else
  387. {
  388. //
  389. // Prepare the core for normal sleep (write 0 to the DEEPSLEEP bit).
  390. //
  391. AM_BFW(SYSCTRL, SCR, SLEEPDEEP, 0);
  392. //
  393. // Go to sleep.
  394. //
  395. AM_ASM_WFI;
  396. }
  397. //
  398. // Restore the interrupt state.
  399. //
  400. am_hal_interrupt_master_set(ui32Critical);
  401. }
  402. //*****************************************************************************
  403. //
  404. //! @brief Enable the floating point module.
  405. //!
  406. //! Call this function to enable the ARM hardware floating point module.
  407. //!
  408. //! @return None.
  409. //
  410. //*****************************************************************************
  411. void
  412. am_hal_sysctrl_fpu_enable(void)
  413. {
  414. //
  415. // Enable access to the FPU in both privileged and user modes.
  416. // NOTE: Write 0s to all reserved fields in this register.
  417. //
  418. AM_REG(SYSCTRL, CPACR) = (AM_REG_SYSCTRL_CPACR_CP11(0x3) |
  419. AM_REG_SYSCTRL_CPACR_CP10(0x3));
  420. }
  421. //*****************************************************************************
  422. //
  423. //! @brief Disable the floating point module.
  424. //!
  425. //! Call this function to disable the ARM hardware floating point module.
  426. //!
  427. //! @return None.
  428. //
  429. //*****************************************************************************
  430. void
  431. am_hal_sysctrl_fpu_disable(void)
  432. {
  433. //
  434. // Disable access to the FPU in both privileged and user modes.
  435. // NOTE: Write 0s to all reserved fields in this register.
  436. //
  437. AM_REG(SYSCTRL, CPACR) = 0x00000000 &
  438. ~(AM_REG_SYSCTRL_CPACR_CP11(0x3) |
  439. AM_REG_SYSCTRL_CPACR_CP10(0x3));
  440. }
  441. //*****************************************************************************
  442. //
  443. //! @brief Enable stacking of FPU registers on exception entry.
  444. //!
  445. //! @param bLazy - Set to "true" to enable "lazy stacking".
  446. //!
  447. //! This function allows the core to save floating-point information to the
  448. //! stack on exception entry. Setting the bLazy option enables "lazy stacking"
  449. //! for interrupt handlers. Normally, mixing floating-point code and interrupt
  450. //! driven routines causes increased interrupt latency, because the core must
  451. //! save extra information to the stack upon exception entry. With the lazy
  452. //! stacking option enabled, the core will skip the saving of floating-point
  453. //! registers when possible, reducing average interrupt latency.
  454. //!
  455. //! @note This function should be called before the floating-point module is
  456. //! used in interrupt-driven code. If it is not called, the core will not have
  457. //! any way to save context information for floating-point variables on
  458. //! exception entry.
  459. //!
  460. //! @return None.
  461. //
  462. //*****************************************************************************
  463. void
  464. am_hal_sysctrl_fpu_stacking_enable(bool bLazy)
  465. {
  466. if ( bLazy )
  467. {
  468. //
  469. // Enable automatic saving of FPU registers on exception entry, using lazy
  470. // context saving.
  471. //
  472. AM_REG(SYSCTRL, FPCCR) |= (AM_REG_SYSCTRL_FPCCR_ASPEN(0x1) |
  473. AM_REG_SYSCTRL_FPCCR_LSPEN(0x1));
  474. }
  475. else
  476. {
  477. //
  478. // Enable automatic saving of FPU registers on exception entry.
  479. //
  480. AM_REG(SYSCTRL, FPCCR) |= AM_REG_SYSCTRL_FPCCR_ASPEN(0x1);
  481. }
  482. }
  483. //*****************************************************************************
  484. //
  485. //! @brief Disable FPU register stacking on exception entry.
  486. //!
  487. //! This function disables all stacking of floating point registers for
  488. //! interrupt handlers.
  489. //!
  490. //! @return None.
  491. //
  492. //*****************************************************************************
  493. void
  494. am_hal_sysctrl_fpu_stacking_disable(void)
  495. {
  496. //
  497. // Enable automatic saving of FPU registers on exception entry, using lazy
  498. // context saving.
  499. //
  500. AM_REG(SYSCTRL, FPCCR) &= ~(AM_REG_SYSCTRL_FPCCR_ASPEN(0x1) |
  501. AM_REG_SYSCTRL_FPCCR_LSPEN(0x1));
  502. }
  503. //*****************************************************************************
  504. //
  505. //! @brief Issue a system wide reset using the AIRCR bit in the M4 system ctrl.
  506. //!
  507. //! This function issues a system wide reset (Apollo POR level reset).
  508. //!
  509. //! @return None.
  510. //
  511. //*****************************************************************************
  512. void
  513. am_hal_sysctrl_aircr_reset(void)
  514. {
  515. //
  516. // Set the system reset bit in the AIRCR register
  517. //
  518. AM_REG(SYSCTRL, AIRCR) = AM_REG_SYSCTRL_AIRCR_VECTKEY(0x5FA) |
  519. AM_REG_SYSCTRL_AIRCR_SYSRESETREQ(1);
  520. }
  521. //*****************************************************************************
  522. //
  523. //! @brief Buck CTimer ISR initializer.
  524. //!
  525. //! @param ui32BuckTimerNumber - Timer number to be used for handling the buck.
  526. //! Must be 0-3.
  527. //!
  528. //! If called with an invalid timer (that is, not 0 - 3, or greater than
  529. //! BUCK_TIMER_MAX), then the workaround will not be enabled.
  530. //!
  531. //! Instead, the bucks will be initialized with a value that will avoid the
  532. //! issues described in the Errata (ERR019). However, this will cause a
  533. //! less efficient energy usage condtion.
  534. //!
  535. //! @return 0.
  536. //
  537. //*****************************************************************************
  538. uint32_t
  539. am_hal_sysctrl_buck_ctimer_isr_init(uint32_t ui32BuckTimerNumber)
  540. {
  541. uint32_t ui32RetVal = 0;
  542. //
  543. // Initialize the input flags
  544. //
  545. g_ui32BuckInputs = 0;
  546. //
  547. // Initialize operation complete flag
  548. //
  549. g_bBuckRestoreComplete = false;
  550. //
  551. // Initialize to assume there is no valid timer.
  552. //
  553. g_ui32BuckTimer = 0;
  554. if ( ui32BuckTimerNumber > BUCK_TIMER_MAX )
  555. {
  556. if ( ( ui32BuckTimerNumber & 0xFFFF0000 ) ==
  557. AM_HAL_SYSCTRL_BUCK_CTIMER_ZX_CONSTANT )
  558. {
  559. //
  560. // The caller is asking for the hard option, which changes the
  561. // settings to the more noise-immune, if less efficient, settings.
  562. // While we're at it, go ahead and save off the current settings.
  563. //
  564. if ( (ui32BuckTimerNumber & 0x0000FFFF) == 0 )
  565. {
  566. setBuckZX(COREZXVALUE, MEMZXVALUE,
  567. SETBUCKZX_USE_PROVIDED_SETTINGS |
  568. SETBUCKZX_SAVE_CURR_SETTINGS |
  569. SETBUCKZX_RESTORE_BOTH );
  570. }
  571. else
  572. {
  573. uint32_t ui32Core, ui32Mem;
  574. //
  575. // Use the setting provided in the parameter.
  576. //
  577. ui32Core = (((ui32BuckTimerNumber & 0x001F) >> 0) - 1) & 0xF;
  578. ui32Mem = (((ui32BuckTimerNumber & 0x1F00) >> 8) - 1) & 0xF;
  579. setBuckZX(ui32Core, ui32Mem,
  580. SETBUCKZX_USE_PROVIDED_SETTINGS |
  581. SETBUCKZX_SAVE_CURR_SETTINGS |
  582. SETBUCKZX_RESTORE_BOTH );
  583. }
  584. }
  585. }
  586. else
  587. {
  588. //
  589. // Save off the current trim settings (but don't change any settings).
  590. //
  591. setBuckZX(0, 0, SETBUCKZX_SAVE_CURR_SETTINGS | SETBUCKZX_RESTORE_BOTH);
  592. //
  593. // The timer number will be maintained as (n + 1). Therefore, a value
  594. // of 0 saved in the global is an invalid timer. 1=timer0, 2=timer1...
  595. //
  596. g_ui32BuckTimer = ui32BuckTimerNumber + 1;
  597. //
  598. // Register the timer ISRs
  599. //
  600. am_hal_ctimer_int_register( AM_HAL_CTIMER_INT_TIMERA0C0 <<
  601. (ui32BuckTimerNumber * 2),
  602. am_hal_sysctrl_buckA_ctimer_isr );
  603. am_hal_ctimer_int_register( AM_HAL_CTIMER_INT_TIMERB0C0 <<
  604. (ui32BuckTimerNumber * 2),
  605. am_hal_sysctrl_buckB_ctimer_isr );
  606. //
  607. // Determine which timer input (A or B) is core buck and which is mem
  608. // buck based on the timer number.
  609. // For CTIMER 0 & 1: Timer A is mem buck, Timer B is core buck
  610. // For CTIMER 2 & 3: Timer A is core buck, Timer B is mem buck
  611. //
  612. if ( (ui32BuckTimerNumber == 0) || (ui32BuckTimerNumber == 1) )
  613. {
  614. //
  615. // Indicate that TimerB is core buck.
  616. //
  617. g_ui32CoreBuck = COREBUCK_TIMERB;
  618. }
  619. else
  620. {
  621. //
  622. // Indicate that TimerA is core buck
  623. //
  624. g_ui32CoreBuck = COREBUCK_TIMERA;
  625. }
  626. //
  627. // Clear and configure the timers
  628. //
  629. am_hal_ctimer_clear(ui32BuckTimerNumber, AM_HAL_CTIMER_BOTH);
  630. am_hal_ctimer_config(ui32BuckTimerNumber,
  631. (am_hal_ctimer_config_t*)&g_sBuckTimer);
  632. //
  633. // Enable the interrupts for timers A and B
  634. //
  635. am_hal_ctimer_int_enable( (AM_HAL_CTIMER_INT_TIMERA0C0 |
  636. AM_HAL_CTIMER_INT_TIMERB0C0 ) <<
  637. (ui32BuckTimerNumber * 2) );
  638. //
  639. // Enable the timer interrupt in the NVIC.
  640. //
  641. am_hal_interrupt_enable(AM_HAL_INTERRUPT_CTIMER);
  642. }
  643. return ui32RetVal;
  644. }
  645. //*****************************************************************************
  646. //
  647. // Get buck update complete status.
  648. //
  649. //*****************************************************************************
  650. bool
  651. am_hal_sysctrl_buck_update_complete(void)
  652. {
  653. return g_bBuckRestoreComplete;
  654. }
  655. //*****************************************************************************
  656. //
  657. // Buck CTIMER ISR (for handling buck switching via TimerA).
  658. //
  659. // Note: This handler assumes that the interrupt is cleared in am_ctimer_isr().
  660. //
  661. //*****************************************************************************
  662. static void
  663. am_hal_sysctrl_buckA_ctimer_isr(void)
  664. {
  665. //
  666. // Begin critical section.
  667. // Although a relatively long time, the following 2us delay is critically
  668. // timed for re-trimming the buck and thus cannot be extended. Therefore,
  669. // we must keep it inside the critical section.
  670. //
  671. AM_CRITICAL_BEGIN_ASM
  672. //
  673. // Delay for 2us.
  674. //
  675. am_hal_flash_delay( FLASH_CYCLES_US(2) );
  676. //
  677. // Determine which buck (core or mem) needs to be updated.
  678. //
  679. if ( g_ui32CoreBuck == COREBUCK_TIMERA )
  680. {
  681. //
  682. // Timer A buck signal is the CORE buck.
  683. // Restore the core buck.
  684. //
  685. setBuckZX(0, 0, SETBUCKZX_RESTORE_CORE_ONLY |
  686. SETBUCKZX_USE_SAVED_SETTINGS );
  687. }
  688. else
  689. {
  690. //
  691. // Timer A buck signal is the MEM buck.
  692. // Restore the mem buck.
  693. //
  694. setBuckZX(0, 0, SETBUCKZX_RESTORE_MEM_ONLY |
  695. SETBUCKZX_USE_SAVED_SETTINGS );
  696. }
  697. g_ui32BuckInputs |= 0x1;
  698. if ( g_ui32BuckInputs == 0x3 )
  699. {
  700. g_bBuckRestoreComplete = true;
  701. g_ui32BuckInputs = 0;
  702. }
  703. //
  704. // End critical section.
  705. //
  706. AM_CRITICAL_END_ASM
  707. }
  708. //*****************************************************************************
  709. //
  710. // Buck CTIMER ISR (for handling buck switching via TimerB).
  711. //
  712. // Note: This handler assumes that the interrupt is cleared in am_ctimer_isr().
  713. //
  714. //*****************************************************************************
  715. static void
  716. am_hal_sysctrl_buckB_ctimer_isr(void)
  717. {
  718. //
  719. // Begin critical section.
  720. // Although a relatively long time, the following 2us delay is critically
  721. // timed for re-trimming the buck and thus cannot be extended. Therefore,
  722. // we must keep it inside the critical section.
  723. //
  724. AM_CRITICAL_BEGIN_ASM
  725. //
  726. // Delay for 2us.
  727. //
  728. am_hal_flash_delay( FLASH_CYCLES_US(2) );
  729. //
  730. // Determine which buck (core or mem) needs to be updated.
  731. //
  732. if ( g_ui32CoreBuck == COREBUCK_TIMERB )
  733. {
  734. //
  735. // Timer B buck signal is the CORE buck.
  736. // Restore the core buck.
  737. //
  738. setBuckZX(0, 0, SETBUCKZX_RESTORE_CORE_ONLY |
  739. SETBUCKZX_USE_SAVED_SETTINGS );
  740. }
  741. else
  742. {
  743. //
  744. // Timer B buck signal is the MEM buck.
  745. // Restore the mem buck.
  746. //
  747. setBuckZX(0, 0, SETBUCKZX_RESTORE_MEM_ONLY |
  748. SETBUCKZX_USE_SAVED_SETTINGS );
  749. }
  750. g_ui32BuckInputs |= 0x2;
  751. if ( g_ui32BuckInputs == 0x3 )
  752. {
  753. g_bBuckRestoreComplete = true;
  754. g_ui32BuckInputs = 0;
  755. }
  756. //
  757. // End critical section.
  758. //
  759. AM_CRITICAL_END_ASM
  760. }
  761. //*****************************************************************************
  762. //
  763. // End Doxygen group.
  764. //! @}
  765. //
  766. //*****************************************************************************