Microprocessor and peripheral 2 assignments for AUTH
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*!
  2. * \file
  3. * NUCLEO_F401RE.h
  4. * \brief
  5. * Nucleo F401RE port file. This file contain the implementation of driver
  6. * calls for F401RE board.
  7. *
  8. * Author: Christos Choutouridis AEM: 8997
  9. * email : <cchoutou@ece.auth.gr>
  10. */
  11. #include "NUCLEO_F401RE.h"
  12. /*
  13. * =============== System ===============
  14. */
  15. static clock_t volatile __ticks; //!< CPU time
  16. static time_t volatile __now; //!< Time in UNIX seconds past 1-Jan-70
  17. static clock_t volatile __sys_freq; //!< The CPU's time frequency (SysTick freq)
  18. /*!
  19. * \brief
  20. * This is the SysTick ISR, micro-system time base service for CPU time.
  21. * \note
  22. * This service implements the SysTick callback function in order
  23. * to provide micro system - os like functionalities to an application
  24. * without RTOS
  25. */
  26. void SysTick_Handler(void) {
  27. // Time
  28. ++__ticks;
  29. if ( !(__ticks % __sys_freq ) )
  30. ++__now; // Do not update __now when we have external time system
  31. }
  32. /*!
  33. * \brief This function configures the source of the time base.
  34. * The time source is configured to have 1ms time base with a dedicated
  35. * Tick interrupt priority.
  36. * \param sf Tick interrupt frequency.
  37. * \retval HAL status
  38. */
  39. __weak HAL_StatusTypeDef HAL_SysTick_Init(clock_t sf) {
  40. SystemCoreClockUpdate ();
  41. /* Configure the SysTick to have interrupt in sf time basis */
  42. if (SysTick_Config (SystemCoreClock/sf) != 0)
  43. return HAL_ERROR;
  44. __sys_freq = sf;
  45. /*Configure the SysTick IRQ priority */
  46. NVIC_SetPriority (SysTick_IRQn, 3U);
  47. /* Return function status */
  48. return HAL_OK;
  49. }
  50. /*!
  51. * Select the system frequency without calling the Setting functionality
  52. * \param sf The desired value
  53. * \return The desired value (enable chaining)
  54. */
  55. __INLINE clock_t HAL_SelectSysTickFreq (clock_t sf){
  56. return __sys_freq =sf;
  57. }
  58. /*!
  59. * \brief Get the __sys_freq.
  60. */
  61. __INLINE clock_t HAL_GetSysTickFreq (void){
  62. return __sys_freq;
  63. }
  64. /*!
  65. * \brief Reconfigure the SysTick and update __sys_freq
  66. * \param sf Tick interrupt frequency (CPU time)
  67. * \return status of the operation
  68. * \arg 0 Success
  69. * \arg 1 Fail
  70. */
  71. int HAL_SetSysTickFreq (clock_t sf) {
  72. /*Configure the SysTick to have interrupt in sf time basis*/
  73. if (__sys_freq != sf) {
  74. // Time base configuration
  75. SystemCoreClockUpdate ();
  76. if (SysTick_Config ( (SystemCoreClock>>3)/sf) != 0)
  77. return 1;
  78. else {
  79. __sys_freq = sf;
  80. return 0;
  81. }
  82. }
  83. return 0;
  84. }
  85. // Take over control of SysTick from HAL library
  86. //! disable HAL_InitTick implementation
  87. HAL_StatusTypeDef
  88. HAL_InitTick(uint32_t TickPriority) { return HAL_OK; }
  89. //! Chain GetTick to our implementation
  90. uint32_t HAL_GetTick(void) { return clock(); }
  91. /*!
  92. * \brief This function provides minimum delay (in CPU time) based
  93. * on variable incremented.
  94. * \param Delay specifies the delay time length, in CPU time.
  95. * \note
  96. * uint32_t is implicitly convertible to clock_t and vice versa.
  97. */
  98. void HAL_Delay(uint32_t Delay) {
  99. uint32_t tickstart = clock();
  100. while((clock() - tickstart) < Delay)
  101. ;
  102. }
  103. /*
  104. * ================ Jiffies ======================
  105. */
  106. /*!
  107. * Provide jiffy compatible set frequency functionality
  108. * \param jf_freq The desire frequency
  109. * \param jiffies The number of steps (jiffies)
  110. * \return The status of the operation
  111. * \arg 0 Success
  112. * \arg 1 Fail
  113. */
  114. int JF_setfreq (uint32_t jf_freq, uint32_t jiffies) {
  115. uint32_t psc=0;
  116. JF_TIMER_CLK_ENABLE();
  117. SystemCoreClockUpdate ();
  118. if (jf_freq)
  119. psc = SystemCoreClock / jf_freq - 1;
  120. if (psc < 0xFFFF) JF_TIMER->PSC = psc;
  121. else return 1;
  122. if (jiffies < 0xFFFF) JF_TIMER->ARR = jiffies;
  123. else return 1;
  124. JF_TIMER->CR1 |= TIM_CR1_CEN;
  125. return 0;
  126. }
  127. /*
  128. * ======== OS like Functionalities ============
  129. */
  130. //! SysTick frequency getter
  131. __INLINE clock_t get_freq (void) {
  132. return __sys_freq;
  133. }
  134. //! SysTick frequency setter
  135. //! \return True on failure
  136. int set_freq (clock_t sf) {
  137. return HAL_SetSysTickFreq (sf);
  138. }
  139. /*!
  140. * \brief
  141. * determines the processor time.
  142. * \return
  143. * the implementation's best approximation to the processor time
  144. * used by the program since program invocation. The time in
  145. * seconds is the value returned divided by the value of the macro
  146. * CLK_TCK or CLOCKS_PER_SEC
  147. */
  148. __INLINE clock_t clock (void) {
  149. return (clock_t) __ticks;
  150. }
  151. /*!
  152. * \brief
  153. * Set the processor time used.
  154. * \param c The new CPU time value
  155. * \return
  156. * The implementation's best approximation to the processor time
  157. * used by the program since program invocation. The time in
  158. * seconds is the value returned divided by the value of the macro
  159. * CLK_TCK or CLOCKS_PER_SEC
  160. */
  161. clock_t setclock (clock_t c) {
  162. return __ticks = c;
  163. }
  164. /*!
  165. * \brief
  166. * determines the current calendar time. The encoding of the value is
  167. * unspecified.
  168. * \return
  169. * The implementations best approximation to the current calendar
  170. * time. If timer is not a null pointer, the return value
  171. * is also assigned to the object it points to.
  172. */
  173. time_t time (time_t *timer) {
  174. if (timer)
  175. *timer = (time_t)__now;
  176. return (time_t)__now;
  177. }
  178. /*!
  179. * \brief
  180. * Sets the system's idea of the time and date. The time,
  181. * pointed to by t, is measured in seconds since the Epoch, 1970-01-01
  182. * 00:00:00 +0000 (UTC).
  183. * \param t Pointer to new system's time and date.
  184. * \return On success, zero is returned. On error, -1 is returned
  185. */
  186. int settime (const time_t *t) {
  187. if (t) {
  188. __now = *t;
  189. return 0;
  190. }
  191. else
  192. return -1;
  193. }
  194. /*
  195. * ============== Cycle count ==============
  196. */
  197. /*!
  198. * Initialize CPU cycle measurement functionality based on DBG
  199. * \return The status of the operation
  200. * \arg LLD_OK Success
  201. * \arg LLD_ERROR Failure
  202. */
  203. LLD_Status_en CYCLE_Init (void) {
  204. CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // enable trace
  205. //DWT->LAR = 0xC5ACCE55; // <-- added unlock access to DWT (ITM, etc.)registers
  206. DWT->CYCCNT = 0; // clear DWT cycle counter
  207. DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; // enable DWT cycle counter
  208. return LLD_OK;
  209. }
  210. //! CPU cycle getter
  211. __INLINE clock_t CYCLE_Get (void) {
  212. return (clock_t)DWT->CYCCNT;
  213. }
  214. //! Helper digital input pin getter
  215. __INLINE uint8_t _DINx (GPIO_TypeDef *port, uint32_t pin) {
  216. return ((port->IDR & pin) != 0) ? 1:0;
  217. }
  218. //! Helper digital output pin setter
  219. __INLINE uint8_t _DOUTx (GPIO_TypeDef *port, uint32_t pin, uint8_t st) {
  220. if (st) port->BSRR = (uint32_t)pin;
  221. else port->BSRR = (uint32_t)pin << 16;
  222. return st;
  223. }
  224. /*
  225. * =============== Digital I/O ===============
  226. * BTN -- PC13
  227. * LED -- PA5 (SB42 is in place) [SB29: PB13]
  228. */
  229. /*!
  230. * Initialize GPIO port pins for Nucleo Board
  231. * \return The status of the operation
  232. * \arg LLD_OK Success
  233. * \arg LLD_ERROR Failure
  234. */
  235. LLD_Status_en NUCLEO_Port_Init (void) {
  236. GPIO_InitTypeDef GPIO_InitType;
  237. // Enable Port clock
  238. __HAL_RCC_GPIOA_CLK_ENABLE ();
  239. __HAL_RCC_GPIOC_CLK_ENABLE ();
  240. // BTN port configuration
  241. GPIO_InitType.Mode = GPIO_MODE_INPUT;
  242. GPIO_InitType.Pin = GPIO_PIN_13;
  243. GPIO_InitType.Pull = GPIO_NOPULL;
  244. HAL_GPIO_Init(GPIOC, &GPIO_InitType);
  245. GPIO_InitType.Mode = GPIO_MODE_OUTPUT_PP;
  246. GPIO_InitType.Speed = GPIO_SPEED_LOW;
  247. GPIO_InitType.Pin = GPIO_PIN_5;
  248. HAL_GPIO_Init(GPIOA, &GPIO_InitType);
  249. return LLD_OK;
  250. }
  251. //! Nucleo's user button reader
  252. uint8_t NUCLEO_BTN (void) {
  253. return _DINx (GPIOC, GPIO_PIN_13);
  254. }
  255. //! Nucleo's LD2 led setter
  256. void NUCLEO_LED (uint8_t on) {
  257. _DOUTx(GPIOA, GPIO_PIN_5, on);
  258. }
  259. /*! Low level driver init functionality
  260. * \return The status of the operation
  261. * \arg LLD_OK Success
  262. * \arg LLD_ERROR Failure
  263. */
  264. LLD_Status_en NUCLEO_Init (clock_t sys_freq) {
  265. HAL_Init();
  266. HAL_SysTick_Init (sys_freq);
  267. CYCLE_Init ();
  268. NUCLEO_Port_Init ();
  269. return LLD_OK;
  270. }