Microprocessor and peripheral 2 assignments for AUTH
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

290 lines
7.2 KiB

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