os_tick_gtim.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /**************************************************************************//**
  2. * @file os_tick_gtim.c
  3. * @brief CMSIS OS Tick implementation for Generic Timer
  4. * @version V1.0.1
  5. * @date 24. November 2017
  6. ******************************************************************************/
  7. /*
  8. * Copyright (c) 2017 ARM Limited. All rights reserved.
  9. *
  10. * SPDX-License-Identifier: Apache-2.0
  11. *
  12. * Licensed under the Apache License, Version 2.0 (the License); you may
  13. * not use this file except in compliance with the License.
  14. * You may obtain a copy of the License at
  15. *
  16. * www.apache.org/licenses/LICENSE-2.0
  17. *
  18. * Unless required by applicable law or agreed to in writing, software
  19. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  20. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  21. * See the License for the specific language governing permissions and
  22. * limitations under the License.
  23. */
  24. #include "os_tick.h"
  25. #include "irq_ctrl.h"
  26. #include "RTE_Components.h"
  27. #include CMSIS_device_header
  28. #ifndef GTIM_IRQ_PRIORITY
  29. #define GTIM_IRQ_PRIORITY 0xFFU
  30. #endif
  31. #ifndef GTIM_IRQ_NUM
  32. #define GTIM_IRQ_NUM SecurePhyTimer_IRQn
  33. #endif
  34. // Timer interrupt pending flag
  35. static uint8_t GTIM_PendIRQ;
  36. // Timer tick frequency
  37. static uint32_t GTIM_Clock;
  38. // Timer load value
  39. static uint32_t GTIM_Load;
  40. // Setup OS Tick.
  41. int32_t OS_Tick_Setup (uint32_t freq, IRQHandler_t handler) {
  42. uint32_t prio, bits;
  43. if (freq == 0U) {
  44. return (-1);
  45. }
  46. GTIM_PendIRQ = 0U;
  47. // Get timer clock
  48. #ifdef SCTR_BASE
  49. GTIM_Clock = *(uint32_t*)(SCTR_BASE+0x20);
  50. #else
  51. // FVP REFCLK CNTControl 100MHz
  52. GTIM_Clock = 100000000UL;
  53. #endif
  54. PL1_SetCounterFrequency(GTIM_Clock);
  55. // Calculate load value
  56. GTIM_Load = (GTIM_Clock / freq) - 1U;
  57. // Disable Generic Timer and set load value
  58. PL1_SetControl(0U);
  59. PL1_SetLoadValue(GTIM_Load);
  60. // Disable corresponding IRQ
  61. IRQ_Disable(GTIM_IRQ_NUM);
  62. IRQ_ClearPending(GTIM_IRQ_NUM);
  63. // Determine number of implemented priority bits
  64. IRQ_SetPriority(GTIM_IRQ_NUM, 0xFFU);
  65. prio = IRQ_GetPriority(GTIM_IRQ_NUM);
  66. // At least bits [7:4] must be implemented
  67. if ((prio & 0xF0U) == 0U) {
  68. return (-1);
  69. }
  70. for (bits = 0; bits < 4; bits++) {
  71. if ((prio & 0x01) != 0) {
  72. break;
  73. }
  74. prio >>= 1;
  75. }
  76. // Adjust configured priority to the number of implemented priority bits
  77. prio = (GTIM_IRQ_PRIORITY << bits) & 0xFFUL;
  78. // Set Private Timer interrupt priority
  79. IRQ_SetPriority(GTIM_IRQ_NUM, prio-1U);
  80. // Set edge-triggered IRQ
  81. IRQ_SetMode(GTIM_IRQ_NUM, IRQ_MODE_TRIG_EDGE);
  82. // Register tick interrupt handler function
  83. IRQ_SetHandler(GTIM_IRQ_NUM, handler);
  84. // Enable corresponding interrupt
  85. IRQ_Enable(GTIM_IRQ_NUM);
  86. // Enable system counter and timer control
  87. #ifdef SCTR_BASE
  88. *(uint32_t*)SCTR_BASE |= 3U;
  89. #endif
  90. // Enable timer control
  91. PL1_SetControl(1U);
  92. return (0);
  93. }
  94. /// Enable OS Tick.
  95. void OS_Tick_Enable (void) {
  96. uint32_t ctrl;
  97. // Set pending interrupt if flag set
  98. if (GTIM_PendIRQ != 0U) {
  99. GTIM_PendIRQ = 0U;
  100. IRQ_SetPending (GTIM_IRQ_NUM);
  101. }
  102. // Start the Private Timer
  103. ctrl = PL1_GetControl();
  104. // Set bit: Timer enable
  105. ctrl |= 1U;
  106. PL1_SetControl(ctrl);
  107. }
  108. /// Disable OS Tick.
  109. void OS_Tick_Disable (void) {
  110. uint32_t ctrl;
  111. // Stop the Private Timer
  112. ctrl = PL1_GetControl();
  113. // Clear bit: Timer enable
  114. ctrl &= ~1U;
  115. PL1_SetControl(ctrl);
  116. // Remember pending interrupt flag
  117. if (IRQ_GetPending(GTIM_IRQ_NUM) != 0) {
  118. IRQ_ClearPending(GTIM_IRQ_NUM);
  119. GTIM_PendIRQ = 1U;
  120. }
  121. }
  122. // Acknowledge OS Tick IRQ.
  123. void OS_Tick_AcknowledgeIRQ (void) {
  124. IRQ_ClearPending (GTIM_IRQ_NUM);
  125. PL1_SetLoadValue(GTIM_Load);
  126. }
  127. // Get OS Tick IRQ number.
  128. int32_t OS_Tick_GetIRQn (void) {
  129. return (GTIM_IRQ_NUM);
  130. }
  131. // Get OS Tick clock.
  132. uint32_t OS_Tick_GetClock (void) {
  133. return (GTIM_Clock);
  134. }
  135. // Get OS Tick interval.
  136. uint32_t OS_Tick_GetInterval (void) {
  137. return (GTIM_Load + 1U);
  138. }
  139. // Get OS Tick count value.
  140. uint32_t OS_Tick_GetCount (void) {
  141. return (GTIM_Load - PL1_GetCurrentValue());
  142. }
  143. // Get OS Tick overflow status.
  144. uint32_t OS_Tick_GetOverflow (void) {
  145. CNTP_CTL_Type cntp_ctl;
  146. cntp_ctl.w = PL1_GetControl();
  147. return (cntp_ctl.b.ISTATUS);
  148. }