|
- /*!
- * \file
- * NUCLEO_F401RE.h
- * \brief
- * Nucleo F401RE port file. This file contain the implementation of driver
- * calls for F401RE board.
- *
- * Author: Christos Choutouridis AEM: 8997
- * email : <cchoutou@ece.auth.gr>
- */
- #include "NUCLEO_F401RE.h"
-
- /*
- * =============== System ===============
- */
-
- static clock_t volatile __ticks; //!< CPU time
- static time_t volatile __now; //!< Time in UNIX seconds past 1-Jan-70
- static clock_t volatile __sys_freq; //!< The CPU's time frequency (SysTick freq)
-
- /*!
- * \brief
- * This is the SysTick ISR, micro-system time base service for CPU time.
- * \note
- * This service implements the SysTick callback function in order
- * to provide micro system - os like functionalities to an application
- * without RTOS
- */
- void SysTick_Handler(void) {
- // Time
- ++__ticks;
- if ( !(__ticks % __sys_freq ) )
- ++__now; // Do not update __now when we have external time system
- }
-
-
- /*!
- * \brief This function configures the source of the time base.
- * The time source is configured to have 1ms time base with a dedicated
- * Tick interrupt priority.
- * \param sf Tick interrupt frequency.
- * \retval HAL status
- */
- __weak HAL_StatusTypeDef HAL_SysTick_Init(clock_t sf) {
- SystemCoreClockUpdate ();
-
- /* Configure the SysTick to have interrupt in sf time basis */
- if (SysTick_Config (SystemCoreClock/sf) != 0)
- return HAL_ERROR;
- __sys_freq = sf;
-
- /*Configure the SysTick IRQ priority */
- NVIC_SetPriority (SysTick_IRQn, 3U);
-
- /* Return function status */
- return HAL_OK;
- }
-
- /*!
- * Select the system frequency without calling the Setting functionality
- * \param sf The desired value
- * \return The desired value (enable chaining)
- */
- __INLINE clock_t HAL_SelectSysTickFreq (clock_t sf){
- return __sys_freq =sf;
- }
-
- /*!
- * \brief Get the __sys_freq.
- */
- __INLINE clock_t HAL_GetSysTickFreq (void){
- return __sys_freq;
- }
-
-
- /*!
- * \brief Reconfigure the SysTick and update __sys_freq
- * \param sf Tick interrupt frequency (CPU time)
- * \return status of the operation
- * \arg 0 Success
- * \arg 1 Fail
- */
- int HAL_SetSysTickFreq (clock_t sf) {
- /*Configure the SysTick to have interrupt in sf time basis*/
- if (__sys_freq != sf) {
- // Time base configuration
- SystemCoreClockUpdate ();
- if (SysTick_Config ( (SystemCoreClock>>3)/sf) != 0)
- return 1;
- else {
- __sys_freq = sf;
- return 0;
- }
- }
- return 0;
- }
-
- // Take over control of SysTick from HAL library
-
- //! disable HAL_InitTick implementation
- HAL_StatusTypeDef
- HAL_InitTick(uint32_t TickPriority) { return HAL_OK; }
-
- //! Chain GetTick to our implementation
- uint32_t HAL_GetTick(void) { return clock(); }
-
- /*!
- * \brief This function provides minimum delay (in CPU time) based
- * on variable incremented.
- * \param Delay specifies the delay time length, in CPU time.
- * \note
- * uint32_t is implicitly convertible to clock_t and vice versa.
- */
- void HAL_Delay(uint32_t Delay) {
- uint32_t tickstart = clock();
-
- while((clock() - tickstart) < Delay)
- ;
- }
-
-
- /*
- * ================ Jiffies ======================
- */
- /*!
- * Provide jiffy compatible set frequency functionality
- * \param jf_freq The desire frequency
- * \param jiffies The number of steps (jiffies)
- * \return The status of the operation
- * \arg 0 Success
- * \arg 1 Fail
- */
- int JF_setfreq (uint32_t jf_freq, uint32_t jiffies) {
- uint32_t psc=0;
-
- JF_TIMER_CLK_ENABLE();
- SystemCoreClockUpdate ();
-
- if (jf_freq)
- psc = SystemCoreClock / jf_freq - 1;
-
- if (psc < 0xFFFF) JF_TIMER->PSC = psc;
- else return 1;
-
- if (jiffies < 0xFFFF) JF_TIMER->ARR = jiffies;
- else return 1;
-
- JF_TIMER->CR1 |= TIM_CR1_CEN;
- return 0;
- }
-
- /*
- * ======== OS like Functionalities ============
- */
-
-
- //! SysTick frequency getter
- __INLINE clock_t get_freq (void) {
- return __sys_freq;
- }
-
- //! SysTick frequency setter
- //! \return True on failure
- int set_freq (clock_t sf) {
- return HAL_SetSysTickFreq (sf);
- }
-
- /*!
- * \brief
- * determines the processor time.
- * \return
- * the implementation's best approximation to the processor time
- * used by the program since program invocation. The time in
- * seconds is the value returned divided by the value of the macro
- * CLK_TCK or CLOCKS_PER_SEC
- */
- __INLINE clock_t clock (void) {
- return (clock_t) __ticks;
- }
-
- /*!
- * \brief
- * Set the processor time used.
- * \param c The new CPU time value
- * \return
- * The implementation's best approximation to the processor time
- * used by the program since program invocation. The time in
- * seconds is the value returned divided by the value of the macro
- * CLK_TCK or CLOCKS_PER_SEC
- */
- clock_t setclock (clock_t c) {
- return __ticks = c;
- }
-
- /*!
- * \brief
- * determines the current calendar time. The encoding of the value is
- * unspecified.
- * \return
- * The implementations best approximation to the current calendar
- * time. If timer is not a null pointer, the return value
- * is also assigned to the object it points to.
- */
- time_t time (time_t *timer) {
- if (timer)
- *timer = (time_t)__now;
- return (time_t)__now;
- }
-
- /*!
- * \brief
- * Sets the system's idea of the time and date. The time,
- * pointed to by t, is measured in seconds since the Epoch, 1970-01-01
- * 00:00:00 +0000 (UTC).
- * \param t Pointer to new system's time and date.
- * \return On success, zero is returned. On error, -1 is returned
- */
- int settime (const time_t *t) {
- if (t) {
- __now = *t;
- return 0;
- }
- else
- return -1;
- }
-
-
- /*
- * ============== Cycle count ==============
- */
- /*!
- * Initialize CPU cycle measurement functionality based on DBG
- * \return The status of the operation
- * \arg LLD_OK Success
- * \arg LLD_ERROR Failure
- */
- LLD_Status_en CYCLE_Init (void) {
- CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // enable trace
- //DWT->LAR = 0xC5ACCE55; // <-- added unlock access to DWT (ITM, etc.)registers
- DWT->CYCCNT = 0; // clear DWT cycle counter
- DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; // enable DWT cycle counter
- return LLD_OK;
- }
-
- //! CPU cycle getter
- __INLINE clock_t CYCLE_Get (void) {
- return (clock_t)DWT->CYCCNT;
- }
-
- //! Helper digital input pin getter
- __INLINE uint8_t _DINx (GPIO_TypeDef *port, uint32_t pin) {
- return ((port->IDR & pin) != 0) ? 1:0;
- }
-
- //! Helper digital output pin setter
- __INLINE uint8_t _DOUTx (GPIO_TypeDef *port, uint32_t pin, uint8_t st) {
- if (st) port->BSRR = (uint32_t)pin;
- else port->BSRR = (uint32_t)pin << 16;
- return st;
- }
-
- /*
- * =============== Digital I/O ===============
- * BTN -- PC13
- * LED -- PA5 (SB42 is in place) [SB29: PB13]
- */
-
- /*!
- * Initialize GPIO port pins for Nucleo Board
- * \return The status of the operation
- * \arg LLD_OK Success
- * \arg LLD_ERROR Failure
- */
- LLD_Status_en NUCLEO_Port_Init (void) {
- GPIO_InitTypeDef GPIO_InitType;
-
- // Enable Port clock
- __HAL_RCC_GPIOA_CLK_ENABLE ();
- __HAL_RCC_GPIOC_CLK_ENABLE ();
-
- // BTN port configuration
- GPIO_InitType.Mode = GPIO_MODE_INPUT;
- GPIO_InitType.Pin = GPIO_PIN_13;
- GPIO_InitType.Pull = GPIO_NOPULL;
-
- HAL_GPIO_Init(GPIOC, &GPIO_InitType);
-
- GPIO_InitType.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitType.Speed = GPIO_SPEED_LOW;
- GPIO_InitType.Pin = GPIO_PIN_5;
-
- HAL_GPIO_Init(GPIOA, &GPIO_InitType);
-
- return LLD_OK;
- }
-
- //! Nucleo's user button reader
- uint8_t NUCLEO_BTN (void) {
- return _DINx (GPIOC, GPIO_PIN_13);
- }
-
- //! Nucleo's LD2 led setter
- void NUCLEO_LED (uint8_t on) {
- _DOUTx(GPIOA, GPIO_PIN_5, on);
- }
-
- /*! Low level driver init functionality
- * \return The status of the operation
- * \arg LLD_OK Success
- * \arg LLD_ERROR Failure
- */
- LLD_Status_en NUCLEO_Init (clock_t sys_freq) {
- HAL_Init();
- HAL_SysTick_Init (sys_freq);
- CYCLE_Init ();
- NUCLEO_Port_Init ();
-
- return LLD_OK;
- }
|