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.
 
 
 
 
 
 

314 lines
7.7 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. * ================ Jiffies ======================
  106. */
  107. int JF_setfreq (uint32_t jf_freq, uint32_t jiffies) {
  108. uint32_t psc=0;
  109. JF_TIMER_CLK_ENABLE();
  110. SystemCoreClockUpdate ();
  111. if (jf_freq)
  112. psc = SystemCoreClock / jf_freq - 1;
  113. if (psc < 0xFFFF) JF_TIMER->PSC = psc;
  114. else return 1;
  115. if (jiffies < 0xFFFF) JF_TIMER->ARR = jiffies;
  116. else return 1;
  117. JF_TIMER->CR1 |= TIM_CR1_CEN;
  118. return 0;
  119. }
  120. /*
  121. * ======== OS like Functionalities ============
  122. */
  123. //! SysTick frequency getter
  124. __INLINE clock_t get_freq (void) {
  125. return __sys_freq;
  126. }
  127. //! SysTick frequency setter
  128. //! \return True on failure
  129. int set_freq (clock_t sf) {
  130. return HAL_SetSysTickFreq (sf);
  131. }
  132. /*!
  133. * \brief
  134. * determines the processor time.
  135. * \return
  136. * the implementation's best approximation to the processor time
  137. * used by the program since program invocation. The time in
  138. * seconds is the value returned divided by the value of the macro
  139. * CLK_TCK or CLOCKS_PER_SEC
  140. */
  141. __INLINE clock_t clock (void) {
  142. return (clock_t) __ticks;
  143. }
  144. /*!
  145. * \brief
  146. * Set the processor time used.
  147. * \param c The new CPU time value
  148. * \return
  149. * The implementation's best approximation to the processor time
  150. * used by the program since program invocation. The time in
  151. * seconds is the value returned divided by the value of the macro
  152. * CLK_TCK or CLOCKS_PER_SEC
  153. */
  154. clock_t setclock (clock_t c) {
  155. return __ticks = c;
  156. }
  157. /*!
  158. * \brief
  159. * determines the current calendar time. The encoding of the value is
  160. * unspecified.
  161. * \return
  162. * The implementations best approximation to the current calendar
  163. * time. If timer is not a null pointer, the return value
  164. * is also assigned to the object it points to.
  165. */
  166. time_t time (time_t *timer) {
  167. if (timer)
  168. *timer = (time_t)__now;
  169. return (time_t)__now;
  170. }
  171. /*!
  172. * \brief
  173. * Sets the system's idea of the time and date. The time,
  174. * pointed to by t, is measured in seconds since the Epoch, 1970-01-01
  175. * 00:00:00 +0000 (UTC).
  176. * \param t Pointer to new system's time and date.
  177. * \return On success, zero is returned. On error, -1 is returned
  178. */
  179. int settime (const time_t *t) {
  180. if (t) {
  181. __now = *t;
  182. return 0;
  183. }
  184. else
  185. return -1;
  186. }
  187. /*
  188. * ============== Cycle count ==============
  189. */
  190. /*!
  191. * Initialize CPU cycle measurement functionality based on DBG
  192. * \return The status of the operation
  193. * \arg LLD_OK Success
  194. * \arg LLD_ERROR Failure
  195. */
  196. LLD_Status_en CYCLE_Init (void) {
  197. CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // enable trace
  198. //DWT->LAR = 0xC5ACCE55; // <-- added unlock access to DWT (ITM, etc.)registers
  199. DWT->CYCCNT = 0; // clear DWT cycle counter
  200. DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; // enable DWT cycle counter
  201. return LLD_OK;
  202. }
  203. //! CPU cycle getter
  204. __INLINE clock_t CYCLE_Get (void) {
  205. return (clock_t)DWT->CYCCNT;
  206. }
  207. //! Helper digital input pin getter
  208. __INLINE uint8_t _DINx (GPIO_TypeDef *port, uint32_t pin) {
  209. return ((port->IDR & pin) != 0) ? 1:0;
  210. }
  211. //! Helper digital output pin setter
  212. __INLINE uint8_t _DOUTx (GPIO_TypeDef *port, uint32_t pin, uint8_t st) {
  213. if (st) port->BSRR = (uint32_t)pin;
  214. else port->BSRR = (uint32_t)pin << 16;
  215. return st;
  216. }
  217. /*
  218. * =============== Digital I/O ===============
  219. * BTN -- PC13
  220. * LED -- PA5 (SB42 is in place) [SB29: PB13]
  221. */
  222. /*!
  223. * Initialize GPIO port pins for Nucleo Board
  224. * \return The status of the operation
  225. * \arg LLD_OK Success
  226. * \arg LLD_ERROR Failure
  227. */
  228. LLD_Status_en NUCLEO_Port_Init (void) {
  229. GPIO_InitTypeDef GPIO_InitType;
  230. // Enable Port clock
  231. __HAL_RCC_GPIOA_CLK_ENABLE ();
  232. __HAL_RCC_GPIOC_CLK_ENABLE ();
  233. // BTN port configuration
  234. GPIO_InitType.Mode = GPIO_MODE_INPUT;
  235. GPIO_InitType.Pin = GPIO_PIN_13;
  236. GPIO_InitType.Pull = GPIO_NOPULL;
  237. HAL_GPIO_Init(GPIOC, &GPIO_InitType);
  238. GPIO_InitType.Mode = GPIO_MODE_OUTPUT_PP;
  239. GPIO_InitType.Speed = GPIO_SPEED_LOW;
  240. GPIO_InitType.Pin = GPIO_PIN_5;
  241. HAL_GPIO_Init(GPIOA, &GPIO_InitType);
  242. return LLD_OK;
  243. }
  244. //! Nucleo's user button reader
  245. uint8_t NUCLEO_BTN (void) {
  246. return _DINx (GPIOC, GPIO_PIN_13);
  247. }
  248. //! Nucleo's LD2 led setter
  249. void NUCLEO_LED (uint8_t on) {
  250. _DOUTx(GPIOA, GPIO_PIN_5, on);
  251. }
  252. /*! Low level driver init functionality
  253. * \return The status of the operation
  254. * \arg LLD_OK Success
  255. * \arg LLD_ERROR Failure
  256. */
  257. LLD_Status_en NUCLEO_Init (clock_t sys_freq) {
  258. HAL_Init();
  259. HAL_SysTick_Init (sys_freq);
  260. CYCLE_Init ();
  261. NUCLEO_Port_Init ();
  262. return LLD_OK;
  263. }