stm32f30_clk.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. /*
  2. * Copyright (C) 2013,2014 by Uwe Bonnes
  3. * (bon@elektron.ikp.physik.tu-darmstadt.de)
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the copyright holders nor the names of
  17. * contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  24. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  27. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  28. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  30. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * For additional information see http://www.ethernut.de/
  34. */
  35. #include <cfg/arch.h>
  36. #include <arch/cm3.h>
  37. #include <arch/cm3/timer.h>
  38. #include <arch/cm3/stm/stm32_clk.h>
  39. #include <cfg/clock.h>
  40. #if defined(MCU_STM32F0) || defined(MCU_STM32F3)
  41. #include <arch/cm3/stm/stm32xxxx.h>
  42. #else
  43. #warning "Unknown STM32 family"
  44. #endif
  45. /* Prepare some defaults if configuration is incomplete */
  46. #if !defined(SYSCLK_SOURCE)
  47. #define SYSCLK_SOURCE SYSCLK_HSI
  48. #endif
  49. static uint32_t SystemCoreClock = 0;
  50. static const uint8_t AHBPrescTable[16] = {
  51. 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
  52. static const uint8_t APBPrescTable[8] = {1, 1, 1, 1, 2, 4, 8, 16};
  53. /* Equalize missing STM32F0 register bits */
  54. #if !defined(RCC_CFGR_PPRE2)
  55. #define RCC_CFGR_PPRE2 0
  56. #endif
  57. #if !defined(RCC_CFGR_PPRE2_0)
  58. #define RCC_CFGR_PPRE2_0 0
  59. #endif
  60. #if defined( RCC_CFGR_PPRE) && !defined( RCC_CFGR_PPRE1)
  61. #define RCC_CFGR_PPRE1 RCC_CFGR_PPRE
  62. #endif
  63. #if defined (RCC_CFGR_PPRE_DIV1) && !defined(RCC_CFGR_PPRE1_DIV1)
  64. #define RCC_CFGR_PPRE1_DIV1 RCC_CFGR_PPRE_DIV1
  65. #endif
  66. #if defined (RCC_CFGR_PPRE_DIV2) && !defined(RCC_CFGR_PPRE1_DIV2)
  67. #define RCC_CFGR_PPRE1_DIV2 RCC_CFGR_PPRE_DIV2
  68. #endif
  69. #if !defined(RCC_CFGR_PPRE2_DIV1)
  70. #define RCC_CFGR_PPRE2_DIV1 0
  71. #endif
  72. #if !defined(RCC_CFGR_PPRE2_DIV2)
  73. #define RCC_CFGR_PPRE2_DIV2 0
  74. #endif
  75. #if defined(FLASH_ACR_LATENCY) && !defined(FLASH_ACR_LATENCY_0)
  76. #define FLASH_ACR_LATENCY_0 FLASH_ACR_LATENCY
  77. #endif
  78. #if defined(RCC_CFGR_PPRE_0) && !defined(RCC_CFGR_PPRE1_0)
  79. #define RCC_CFGR_PPRE1_0 RCC_CFGR_PPRE_0
  80. #endif
  81. /*---------------- Clock Setup Procedure ------------------------------
  82. *
  83. * Clock system ist arranged like this:
  84. *
  85. * /Q------------------------------ USB
  86. * | ,--------------- CPU
  87. * | +--------------- SDIO
  88. * (1)4-32MHz HSE-+--/M*N+---+-AHBPRES---+-- APB1PRESC--- APB1
  89. * | | +-- ABP2PRESC--- ABP2
  90. * 8MHz HSI ------+----------' '-- ADCPRESC---- ADC
  91. * +-- Flash
  92. * '-- Option byte Loader
  93. *
  94. * M = 1..16
  95. * N = 2..16
  96. * Q = 1/1.5
  97. *
  98. * ***** Setup of system clock configuration *****
  99. *
  100. * 1) Select system clock sources
  101. *
  102. * To setup system to use HSI call: SetSysClockSource( SYSCLK_HSI);
  103. * To setup system to use HSE call: SetSysClockSource( SYSCLK_HSE);
  104. *
  105. * To setup system to use the PLL output, first setup the PLL source:
  106. * SetPllClockSource( PLLCLK_HSI);
  107. * or
  108. * SetPllClockSource( PLLCLK_HSE);
  109. * Then call SetSysClockSource( SYSCLK_PLL);
  110. *
  111. * 2) Configure prescalers
  112. * After selecting the right clock sources, the prescalers need to
  113. * be configured:
  114. * Call SetSysClock(); to do this automatically.
  115. *
  116. */
  117. /*!
  118. * \brief Update SystemCoreClock according to Clock Register Values
  119. *
  120. * This function reads out the CPUs clock and PLL registers and assembles
  121. * the actual clock speed values into the SystemCoreClock local variable.
  122. */
  123. void SystemCoreClockUpdate(void)
  124. {
  125. RCC_TypeDef *rcc = (RCC_TypeDef*) RCC_BASE;
  126. uint32_t cfgr;
  127. uint32_t tmp = 0;
  128. uint32_t hpre;
  129. /* Get SYSCLK source ---------------------------------------------------*/
  130. cfgr = RCC->CFGR;
  131. switch(cfgr & RCC_CFGR_SWS) {
  132. case RCC_CFGR_SWS_HSE:
  133. tmp = HSE_VALUE;
  134. break;
  135. case RCC_CFGR_SWS_PLL: {
  136. uint32_t cfgr2 = rcc->CFGR2;
  137. uint32_t prediv;
  138. uint32_t pllmull;
  139. prediv = (cfgr2 & RCC_CFGR2_PREDIV1) >> _BI32(RCC_CFGR2_PREDIV1_0);
  140. prediv += 1;
  141. pllmull = (cfgr & RCC_CFGR_PLLMULL) >> _BI32(RCC_CFGR_PLLMULL_0);
  142. pllmull += 2;
  143. if (pllmull > 16)
  144. pllmull = 16;
  145. if ((cfgr & RCC_CFGR_PLLSRC ) == RCC_CFGR_PLLSRC )
  146. tmp = HSE_VALUE;
  147. else
  148. tmp = HSI_VALUE / 2;
  149. tmp = (tmp / prediv) * pllmull;
  150. break;
  151. }
  152. default:
  153. tmp = HSI_VALUE;
  154. }
  155. hpre = (cfgr & RCC_CFGR_HPRE) >> _BI32(RCC_CFGR_HPRE_0);
  156. SystemCoreClock = tmp >> AHBPrescTable[hpre];
  157. }
  158. /* Functional same as F1 */
  159. /*!
  160. * \brief Control HSE clock.
  161. *
  162. * \param ena 0 disable clock, any other value enable it.
  163. * \return 0 on success, -1 on HSE start failed.
  164. */
  165. int CtlHseClock( uint8_t ena)
  166. {
  167. int rc = 0;
  168. uint32_t tout = HSE_STARTUP_TIMEOUT;
  169. volatile uint32_t HSEStatus = 0;
  170. if( ena) {
  171. /* Enable HSE */
  172. RCC->CR |= RCC_CR_HSEON;
  173. #if defined(HSE_BYPASS)
  174. /* Assume HSE if off */
  175. RCC->CR |= RCC_CR_HSEBYP;
  176. #else
  177. RCC->CR &= ~RCC_CR_HSEBYP;
  178. #endif
  179. /* Wait till HSE is ready or time out is reached */
  180. do {
  181. tout--;
  182. HSEStatus = RCC->CR & RCC_CR_HSERDY;
  183. } while((HSEStatus == 0) && (tout > 0));
  184. if ((RCC->CR & RCC_CR_HSERDY) == RESET) {
  185. /* HSE failed to start */
  186. rc = -1;
  187. }
  188. }
  189. else {
  190. /* Disable HSE clock */
  191. RCC->CR &= ~RCC_CR_HSEON;
  192. }
  193. return rc;
  194. }
  195. /* Functional same as F1 */
  196. /*!
  197. * \brief Control HSI clock.
  198. *
  199. * \param ena 0 disable clock, any other value enable it.
  200. * \return 0 on success, -1 on HSI start failed.
  201. */
  202. int CtlHsiClock( uint8_t ena)
  203. {
  204. int rc = 0;
  205. uint32_t tout = HSE_STARTUP_TIMEOUT;
  206. volatile uint32_t HSIStatus = 0;
  207. if( ena) {
  208. /* Enable HSI */
  209. RCC->CR |= RCC_CR_HSION;
  210. /* Wait till HSI is ready or time out is reached */
  211. do {
  212. tout--;
  213. HSIStatus = RCC->CR & RCC_CR_HSIRDY;
  214. } while((HSIStatus == 0) && (tout > 0));
  215. if ((RCC->CR & RCC_CR_HSIRDY) == RESET) {
  216. /* HSI failed to start */
  217. rc = -1;
  218. }
  219. }
  220. else {
  221. /* Disable HSE clock */
  222. RCC->CR &= ~RCC_CR_HSION;
  223. }
  224. return rc;
  225. }
  226. /* Functional same as F1 */
  227. /*!
  228. * \brief Control PLL clock.
  229. *
  230. * \param ena 0 disable clock, any other value enable it.
  231. * \return 0 on success, -1 on PLL start failed.
  232. */
  233. int CtlPllClock( uint8_t ena)
  234. {
  235. int rc = 0;
  236. uint32_t tout = HSE_STARTUP_TIMEOUT;
  237. volatile uint32_t PLLStatus = 0;
  238. if( ena) {
  239. /* Enable PLL */
  240. RCC->CR |= RCC_CR_PLLON;
  241. /* Wait till PLL is ready or time out is reached */
  242. do {
  243. tout--;
  244. PLLStatus = RCC->CR & RCC_CR_PLLRDY;
  245. } while((PLLStatus == 0) && (tout > 0));
  246. if ((RCC->CR & RCC_CR_PLLRDY) == RESET) {
  247. /* PLL failed to start */
  248. rc = -1;
  249. }
  250. }
  251. else {
  252. /* Disable HSE clock */
  253. RCC->CR &= ~RCC_CR_PLLON;
  254. }
  255. return rc;
  256. }
  257. /*!
  258. * \brief Configures the System clock source: HSE or HSI.
  259. * \note This function should be used with PLL disables
  260. * \param src is one of PLLCLK_HSE, PLLCLK_HSI.
  261. * \return 0 if clock is running ale -1.
  262. */
  263. int SetPllClockSource( int src)
  264. {
  265. int rc = -1;
  266. if (src == PLLCLK_HSE) {
  267. rc = CtlHseClock(ENABLE);
  268. if (rc==0) {
  269. CM3BBSET(RCC_BASE, RCC_TypeDef, CFGR2, _BI32(RCC_CFGR_PLLSRC_PREDIV1));
  270. }
  271. }
  272. else if (src == PLLCLK_HSI) {
  273. rc = CtlHsiClock(ENABLE);
  274. /* Select HSI/2 as PLL clock source */
  275. if (rc==0) {
  276. CM3BBCLR(RCC_BASE, RCC_TypeDef, CFGR2, _BI32(RCC_CFGR_PLLSRC_PREDIV1));
  277. }
  278. }
  279. return rc;
  280. }
  281. /*!
  282. * \brief Configures the System clock source: HSI, HS or PLL.
  283. * \note This function should be used only after reset.
  284. * \param src is one of SYSCLK_HSE, SYSCLK_HSI or SYSCLK_PLL.
  285. * \return 0 if selected clock is running else -1.
  286. */
  287. int SetSysClockSource( int src)
  288. {
  289. int rc = -1;
  290. if (src == SYSCLK_HSE) {
  291. rc = CtlHseClock(ENABLE);
  292. if (rc == 0) {
  293. /* Select HSE as system clock source */
  294. RCC->CFGR &= ~RCC_CFGR_SW;
  295. RCC->CFGR |= RCC_CFGR_SW_HSE;
  296. /* Wait till HSE is used as system clock source */
  297. while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSE);
  298. }
  299. }
  300. else if (src == SYSCLK_HSI) {
  301. rc = CtlHsiClock(ENABLE);
  302. if (rc == 0) {
  303. /* Select HSI as system clock source */
  304. RCC->CFGR &= ~RCC_CFGR_SW;
  305. RCC->CFGR |= RCC_CFGR_SW_HSI;
  306. /* Wait till HSI is used as system clock source */
  307. while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI);
  308. }
  309. }
  310. else if (src == SYSCLK_PLL) {
  311. rc = CtlPllClock(ENABLE);
  312. if (rc == 0) {
  313. /* Select HSI as system clock source */
  314. RCC->CFGR &= ~RCC_CFGR_SW;
  315. RCC->CFGR |= RCC_CFGR_SW_PLL;
  316. /* Wait till PLL is used as system clock source */
  317. while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
  318. }
  319. }
  320. /* Update core clock information */
  321. SystemCoreClockUpdate();
  322. return rc;
  323. }
  324. #if (SYSCLK_SOURCE == SYSCLK_HSI) || (SYSCLK_SOURCE == SYSCLK_HSE)
  325. /*!
  326. * \brief Configures the System clock coming from HSE or HSI oscillator.
  327. *
  328. * Enable HSI/HSE clock and setup HCLK, PCLK2 and PCLK1 prescalers.
  329. *
  330. * \param None.
  331. * \return 0 on success, -1 on fault of HSE.
  332. */
  333. int SetSysClock(void)
  334. {
  335. int rc = 0;
  336. register uint32_t cfgr;
  337. /* Todo: Check Voltage range! Here 2.7-3.6 Volt is assumed */
  338. /* For 2.7-3.6 Volt up to 30 MHz no Wait state required */
  339. cfgr = RCC->CFGR;
  340. cfgr &= ~(RCC_CFGR_HPRE|RCC_CFGR_PPRE1|RCC_CFGR_PPRE2);
  341. /* HCLK = SYSCLK */
  342. cfgr |= (uint32_t)RCC_CFGR_HPRE_DIV1;
  343. /* PCLK2 = HCLK */
  344. cfgr |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
  345. /* PCLK1 = HCLK */
  346. cfgr |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
  347. RCC->CFGR = cfgr;
  348. rc = SetSysClockSource(SYSCLK_SOURCE);
  349. return rc;
  350. }
  351. #elif (SYSCLK_SOURCE == SYSCLK_PLL)
  352. /**
  353. * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2
  354. * and PCLK1 prescalers.
  355. * @note This function should be used only after reset.
  356. * @param None
  357. * @retval None
  358. */
  359. #if (PLLCLK_SOURCE==PLLCLK_HSE)
  360. #define PLLCLK_IN HSE_VALUE
  361. #if (PLLCLK_MULT == 0 ) && (PLLCLK_DIV == 0)
  362. #undef PLLCLK_DIV
  363. #if (((PLLCLK_IN % 24000000) == 0) && ((SYSCLK_FREQ % 24000000) == 0))
  364. #define PLLCLK_DIV (PLLCLK_IN / 24000000)
  365. #elif (((PLLCLK_IN % 16000000) == 0) && ((SYSCLK_FREQ % 16000000) == 0))
  366. #define PLLCLK_DIV (PLLCLK_IN / 16000000)
  367. #elif (((PLLCLK_IN % 14400000) == 0) && ((SYSCLK_FREQ % 14400000) == 0))
  368. #define PLLCLK_DIV (PLLCLK_IN / 14400000)
  369. #elif (((PLLCLK_IN % 12000000) == 0) && ((SYSCLK_FREQ % 12000000) == 0))
  370. #define PLLCLK_DIV (PLLCLK_IN / 12000000)
  371. #elif (((PLLCLK_IN % 9600000) == 0) && ((SYSCLK_FREQ % 9600000) == 0))
  372. #define PLLCLK_DIV (PLLCLK_IN / 9600000)
  373. #elif (((PLLCLK_IN % 8000000) == 0) && ((SYSCLK_FREQ % 8000000) == 0))
  374. #define PLLCLK_DIV (PLLCLK_IN / 8000000)
  375. #elif (((PLLCLK_IN % 6000000) == 0) && ((SYSCLK_FREQ % 6000000) == 0))
  376. #define PLLCLK_DIV (PLLCLK_IN / 6000000)
  377. #elif (((PLLCLK_IN % 4800000) == 0) && ((SYSCLK_FREQ % 4800000) == 0))
  378. #define PLLCLK_DIV (PLLCLK_IN / 4800000)
  379. #elif (((PLLCLK_IN % 4000000) == 0) && ((SYSCLK_FREQ % 4000000) == 0))
  380. #define PLLCLK_DIV (PLLCLK_IN / 4000000)
  381. #elif (((PLLCLK_IN % 3000000) == 0) && ((SYSCLK_FREQ % 3000000) == 0))
  382. #define PLLCLK_DIV (PLLCLK_IN / 3000000)
  383. #endif
  384. #endif
  385. #else /* HSI Used*/
  386. /* HSI_VALUE value from vendor provided file as illegal type */
  387. #define PLLCLK_IN 4000000
  388. #if (PLLCLK_MULT == 0 ) && (PLLCLK_DIV == 0)
  389. #undef PLLCLK_DIV
  390. #define PLLCLK_DIV 1
  391. #elif (PLLCLK_DIV != 0)
  392. #warning "HSI/2 Input has no clock divider"
  393. #endif
  394. #endif
  395. #if (PLLCLK_MULT == 0 ) && (PLLCLK_DIV > 0)
  396. #undef PLLCLK_MULT
  397. #define PLLCLK_MULT (SYSCLK_FREQ/(PLLCLK_IN / PLLCLK_DIV))
  398. #endif
  399. #if (PLLCLK_DIV < 1) || (PLLCLK_DIV > 16)
  400. # warning "Illegal PLLCLK_DIV value"
  401. #endif
  402. #if (PLLCLK_MULT < 2) || (PLLCLK_MULT > 16)
  403. # warning "Illegal PLLCLK_MULT value"
  404. #endif
  405. #if (PLLCLK_IN /PLLCLK_DIV * PLLCLK_MULT > 72000000)
  406. #warning "Clock frequency too high"
  407. #elif (PLLCLK_IN /PLLCLK_DIV * PLLCLK_MULT >48000000)
  408. #define NUT_FLASH_LATENCY FLASH_ACR_LATENCY_1
  409. #if defined(MCU_STM32F0)
  410. #warning "Clock frequency too high"
  411. #endif
  412. #elif (PLLCLK_IN /PLLCLK_DIV * PLLCLK_MULT >24000000)
  413. #define NUT_FLASH_LATENCY FLASH_ACR_LATENCY_0
  414. #else
  415. #define NUT_FLASH_LATENCY 0
  416. #endif
  417. /*
  418. Easy Approach:
  419. Try to reach fpll = 72 Mhz with M/N.
  420. */
  421. int SetSysClock(void)
  422. {
  423. int rc = 0;
  424. uint32_t rcc_reg;
  425. RCC->APB1ENR |= RCC_APB1ENR_PWREN;
  426. rcc_reg = RCC->CFGR;
  427. rcc_reg &= ~(RCC_CFGR_PLLMULL |RCC_CFGR_PLLSRC |RCC_CFGR_PPRE2 | RCC_CFGR_PPRE1 |RCC_CFGR_HPRE);
  428. #if defined(MCU_STM32F0)
  429. /* APB Bus can run with full SYSCLK speed (48 MHz) */
  430. rcc_reg |= ((PLLCLK_MULT -2) * RCC_CFGR_PLLMULL_0);
  431. #else
  432. /* APB1 Bus (Slow APB) bus can only run with half SYSCLK speed 36 MHz) */
  433. rcc_reg |= ((PLLCLK_MULT -2) * RCC_CFGR_PLLMULL_0) | RCC_CFGR_PPRE1_DIV2;
  434. #endif
  435. #if (PLLCLK_SOURCE == PLLCLK_HSE)
  436. if (CtlHseClock(ENABLE) != 0)
  437. return -1;
  438. rcc_reg |= RCC_CFGR_PLLSRC;
  439. #else
  440. if (CtlHsiClock(ENABLE) != 0)
  441. return -1;
  442. #endif
  443. RCC->CFGR = rcc_reg;
  444. rcc_reg = FLASH->ACR;
  445. rcc_reg &= ~FLASH_ACR_LATENCY;
  446. rcc_reg |= NUT_FLASH_LATENCY | FLASH_ACR_PRFTBE ;
  447. FLASH->ACR = rcc_reg;
  448. rcc_reg = RCC->CFGR2;
  449. rcc_reg &= ~(RCC_CFGR2_PREDIV1);
  450. /* HCLK = SYSCLK, PCLK2 = HCLK , PCLK1 = HCLK/2 */
  451. rcc_reg |= (PLLCLK_DIV - 1);
  452. RCC->CFGR2 = rcc_reg;
  453. /* Start PLL, wait ready and switch to it as clock source */
  454. rc = SetSysClockSource(SYSCLK_SOURCE);
  455. if (rc) {
  456. /* Something went wrong with the PLL startup! */
  457. SetSysClockSource(SYSCLK_HSI);
  458. return rc;
  459. }
  460. return rc;
  461. }
  462. #endif /* (SYSCLK_SOURCE == SYSCLK_HSI) || (SYSCLK_SOURCE == SYSCLK_HSE) */
  463. /**
  464. * @brief requests System clock frequency
  465. *
  466. * @note This function should be used only after reset.
  467. * @param None
  468. * @retval None
  469. */
  470. uint32_t SysCtlClockGet(void)
  471. {
  472. SystemCoreClockUpdate();
  473. return SystemCoreClock;
  474. }
  475. /**
  476. * @brief requests frequency of the given clock
  477. *
  478. * @param idx NUT_HWCLK Index
  479. * @retval clock or 0 if idx points to an invalid clock
  480. */
  481. uint32_t STM_ClockGet(int idx)
  482. {
  483. SystemCoreClockUpdate();
  484. switch(idx) {
  485. case NUT_HWCLK_CPU:
  486. return SystemCoreClock;
  487. break;
  488. case NUT_HWCLK_PCLK1: {
  489. uint32_t tmp = (RCC->CFGR & RCC_CFGR_PPRE1) >> _BI32( RCC_CFGR_PPRE1_0);
  490. return SystemCoreClock/APBPrescTable[tmp];
  491. break;
  492. }
  493. case NUT_HWCLK_PCLK2: {
  494. uint32_t tmp = (RCC->CFGR & RCC_CFGR_PPRE2) >> _BI32( RCC_CFGR_PPRE2_0);
  495. return SystemCoreClock/APBPrescTable[tmp];
  496. break;
  497. }
  498. default:
  499. return 0;
  500. break;
  501. }
  502. }