stm32f1_clk.c 17 KB

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