Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 
 

86 rader
2.8 KiB

  1. /** @defgroup clk_file Clock peripheral API
  2. * @ingroup peripheral_apis
  3. * @brief SWM050 Clock API.
  4. * LGPL License Terms @ref lgpl_license
  5. * @author @htmlonly © @endhtmlonly 2019
  6. * Caleb Szalacinski <contact@skiboy.net>
  7. */
  8. /*
  9. * This file is part of the libopencm3 project.
  10. *
  11. * Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net>
  12. *
  13. * This library is free software: you can redistribute it and/or modify
  14. * it under the terms of the GNU Lesser General Public License as published by
  15. * the Free Software Foundation, either version 3 of the License, or
  16. * (at your option) any later version.
  17. *
  18. * This library is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU Lesser General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU Lesser General Public License
  24. * along with this library. If not, see <http://www.gnu.org/licenses/>.
  25. */
  26. /**@{*/
  27. #include <libopencm3/swm050/clk.h>
  28. #include <libopencm3/swm050/sysctl.h>
  29. /*---------------------------------------------------------------------------*/
  30. /** @brief Setup and change the system clock multiplier and divider
  31. Change system clock speed and wait for the clock to stabilize. The clock only
  32. needs time to stabilize on the first invocation of this function. This should be
  33. run at startup if you want to have a stable clock before doing anything.
  34. @param[in] mhz Base clock speed @ref clk_speeds
  35. The base clock speed, before the clock divider
  36. @param[in] div Clock divider
  37. Takes values from 0 to 1023 (in reality the possible values are the even
  38. numbers from 2 to 1022, as well as the number 1). Anything more than the
  39. first 10 bits is stripped off of the value. If the value is 0, it will
  40. be treated as a 1. All odd values other than 1 are rounded down to the
  41. closest even value, due to the fact that all odd values are treated by
  42. the register as a 1, which would likely be unexpected. A value of 0
  43. would also normally be treated as a 2, which would also be unexpected
  44. behavior.
  45. */
  46. void clk_speed(enum clk_speeds mhz, uint16_t div)
  47. {
  48. static bool first_run = true;
  49. if (first_run) {
  50. first_run = false;
  51. clk_speed(CLK_18MHZ, 1);
  52. for (uint16_t i = 0; i < 10000; ++i) {
  53. __asm__("nop");
  54. }
  55. /* The speed doesn't need to be changed
  56. a second time if the user wants 18Mhz. */
  57. if ((mhz == CLK_18MHZ) && (div <= 1)) {
  58. return;
  59. }
  60. if ((mhz == CLK_36MHZ) && (div == 2)) {
  61. return;
  62. }
  63. }
  64. if (mhz == CLK_36MHZ) {
  65. SYSCTL_SYS_DBLF |= BIT0;
  66. } else {
  67. SYSCTL_SYS_DBLF &= ~BIT0;
  68. }
  69. if (div <= 1) {
  70. SYSCTL_SYS_CFG_0 |= BIT0;
  71. } else {
  72. uint32_t masked_reg32 = SYSCTL_SYS_CFG_0 & CLK_MASK;
  73. SYSCTL_SYS_CFG_0 = masked_reg32 | (div & ~(CLK_MASK | 0x1));
  74. }
  75. }
  76. /**@}*/