Init commit

- Import assignment 1 files and repo
 - Assignment 2 code
This commit is contained in:
2020-05-24 14:56:52 +03:00
commit 0f28637aed
18 changed files with 1242 additions and 0 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

+289
View File
@@ -0,0 +1,289 @@
/*!
* \file
* NUCLEO_F401RE.h
* \brief
* Nucleo F401RE port file. This file contain the implementation of driver
* calls for F401RE board.
*
* Created on: May 23, 2020
* 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)
;
}
/*
* ======== 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;
}
/*
* =============== Digital I/O ===============
* BTN -- PC13
* LED -- PA5 (SB42 is in place) [SB29: PB13]
*/
//! Helper digital input pin getter
static __INLINE uint8_t _DINx (GPIO_TypeDef *port, uint32_t pin) {
return ((port->IDR & pin) != 0) ? 1:0;
}
//! Helper digital output pin setter
static __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;
}
/*!
* Initialize GPIO port pins for Nucleo Board
* \return The status of the operation
* \arg LLD_OK Success
* \arg LLD_ERROR Failure
*/
LLD_Status_en 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 BTN (void) {
return _DINx (GPIOC, GPIO_PIN_13);
}
//! Nucleo's LD2 led setter
void 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 LLD_Init (clock_t sys_freq) {
HAL_Init();
HAL_SysTick_Init (sys_freq);
CYCLE_Init ();
Port_Init ();
return LLD_OK;
}
+137
View File
@@ -0,0 +1,137 @@
/*!
* \file
* NUCLEO_F401RE.h
* \brief
* Nucleo F401RE port file. This file contain the implementation of driver
* calls for F401RE board.
*
* Created on: May 23, 2020
* Author: Christos Choutouridis AEM: 8997
* email : <cchoutou@ece.auth.gr>
*/
#ifndef NUCLEO_F401RE_H_
#define NUCLEO_F401RE_H_
#include <stm32f4xx.h>
#include <stm32f4xx_hal.h>
#include <core_cm4.h>
/*
* ========= Data types ========
*/
//! Driver status return type
typedef enum {
LLD_OK = 0, //!< Indicate successful operation
LLD_ERROR //!< Indicate Error
}LLD_Status_en;
typedef uint8_t din_t;
//typedef int adc_t;
#define OFF (0)
#define ON (!OFF)
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
/*
* =============== System ===============
*/
#if defined ( __GNUC__ ) && !defined (__CC_ARM)
#include <sys/types.h>
#endif
#include <limits.h>
/*
* Also defined in types.h
*/
#ifndef _CLOCK_T_
#define _CLOCK_T_ unsigned long /* clock() */
typedef _CLOCK_T_ clock_t; /*!< CPU time type */
#endif
#ifndef _TIME_T_
#define _TIME_T_ long /* time() */
typedef _TIME_T_ time_t; /*!< date/time in unix secs past 1-Jan-70 type for 68 years*/
#endif
/*
* Helper macros
*/
#define _CLOCK_T_MAX_VALUE_ (ULONG_MAX) //!< Helper macro for maximum signed CPU time calculations
/*!
* Calculate the positive time difference of _t2_ and _t1_, where
* _t1_, _t2_ are clock_t values
* \note
* _t2_ event comes is AFTER _t1_
*
* ex:
* 0 1 2 3 4 5 6 7 8 9
* ^ ^
* | |
* a b
*
* if : t1=a, t2=b then dt = b-a = t2 - t1
* if : t1=b, t2=a then dt = 9 - (b-a) + 1 = UMAX - (t1-t2) + 1
*
*/
#define _CLOCK_DIFF(_t2_, _t1_) ( ((_t2_)>(_t1_)) ? ((_t2_)-(_t1_)) : (_CLOCK_T_MAX_VALUE_ - ((_t1_) - (_t2_)) + 1) )
/*
* CPU time macros
*/
#define msec2CPUtime(_ms_) (((_ms_) * get_freq()) / 1000)
#define sec2CPUtime(_s_) ((_s_) * get_freq())
#define CPUtime2msec(_t_) (((_t_) * 1000) / get_freq())
#define CPUtime2sec(_t_) ((_t_) / get_freq())
HAL_StatusTypeDef HAL_SysTick_Init(clock_t sf);
clock_t HAL_SelectSysTickFreq (clock_t sf);
clock_t HAL_GetSysTickFreq (void);
int HAL_SetSysTickFreq (clock_t sf);
/*
* OS like Functionalities
*/
clock_t get_freq (void);
int set_freq (clock_t sf);
clock_t clock (void);
clock_t setclock (clock_t c);
time_t time (time_t *timer);
int settime (const time_t *t);
/*
* ============== Cycle count ==============
*/
LLD_Status_en CYCLE_Init (void);
clock_t CYCLE_Get (void);
/*
* =============== Digital I/O ===============
* BTN -- PC13
* LED -- PA5 (SB42 is in place) [SB29: PB13]
*/
LLD_Status_en Port_Init (void);
uint8_t BTN (void);
void LED (uint8_t on);
/*
* ============= Board Init ==============
*/
LLD_Status_en LLD_Init (clock_t sys_freq);
#endif /* NUCLEO_F401RE_H_ */
+63
View File
@@ -0,0 +1,63 @@
/*!
* \file
* assign2_impl.h
* \brief
* Assignment 2 application header
*
* Created on: May 23, 2020
* Author: Christos Choutouridis AEM: 8997
* email : <cchoutou@ece.auth.gr>
*/
#ifndef ASSIGN2_IMPL_H_
#define ASSIGN2_IMPL_H_
#include "NUCLEO_F401RE.h"
#include <stdlib.h>
#include <math.h>
/*
* ============= User defines ===============
*/
#define SYSTICK_FREQ (1000) //!< 1000Hz => 1msec accuracy
#define MODE_LEADING_EDGE (1) //!< Start counting as soon as the led is switched on
#define MODE_TRAILING_EDGE (2) //!< Start counting as soon as the led is switched off (Motor sport style)
//! If there is no Pre-define MODE, select one here
#ifndef MODE
#define MODE MODE_TRAILING_EDGE
#endif
#define MEASUREMENTS (5) //!< The number of measurements for each experiment
//! elect the maximum waiting time before the visual trigger.
#define MAX_WAIT_TIME sec2CPUtime(10)
//! Select if we need cycle counting also.
#define CYCLE_COUNTING (1)
/*
* ============= Data types ===============
*/
//! Select the application wide accuracy of the floating point type.
typedef float fp_data_t; //!< floating point data alias.
/*!
* Statistical data structure
*/
typedef struct {
fp_data_t average; //!< The average response time of the experiment
fp_data_t median; //!< The median of the times
fp_data_t std_dev; //!< Standard deviation
} stats_t;
fp_data_t average (const clock_t *t, size_t n);
fp_data_t median (const clock_t *t, size_t n);
fp_data_t std_deviation (const clock_t* t, size_t n);
void leading (clock_t *out, size_t n);
void trailing (clock_t *out, size_t n);
#endif /* ASSIGN2_IMPL_H_ */
+145
View File
@@ -0,0 +1,145 @@
/*!
* \file
* main.c
* \brief
* Main application file
*
* Created on: May 23, 2020
* Author: Christos Choutouridis AEM: 8997
* email : <cchoutou@ece.auth.gr>
*/
#include "assign2_impl.h"
/*
* Global data
*/
stats_t stats;
/*!
* Compare functionality for qsort
* \param a left hand site
* \param b right hand site
* \return stdlib requirements
* \arg -1 a<b
* \arg 0 a==b
* \arg 1 a>b
*/
static int cmpfunc (const void * a, const void * b) {
fp_data_t v = *(fp_data_t*)a - *(fp_data_t*)b;
return (v < 0) ? -1 : (v > 0) ? 1 : 0;
}
/*!
* Calculates and return the average of an array of measurements
* \param t Pointer to measurements
* \param n Size of measurements array
* \return The average
*/
fp_data_t average (const clock_t *t, size_t n) {
fp_data_t ret =0;
for (size_t i=0 ; i<n ; ++i)
ret += t[i];
return ret / n;
}
/*!
* Calculates and return the median of an array of measurements
* \param t Pointer to measurements
* \param n Size of measurements array
* \return The average
*/
fp_data_t median (const clock_t *t, size_t n) {
qsort ((void*)t, n, sizeof(t[0]), cmpfunc);
return (n % 2) ? t[n/2] : (t[n/2] + t[n/2 -1]) /2;
}
/*!
* Calculates and return the std. deviation of an array of measurements
* \param t Pointer to measurements
* \param n Size of measurements array
* \return The average
*/
fp_data_t std_deviation (const clock_t* t, size_t n) {
fp_data_t av = average (t, n);
fp_data_t s =0;
for (size_t i=0 ; i<n ; ++i) {
s += (t[i]-av)*(t[i]-av);
}
return sqrt (s/n);
}
/*!
* Leading edge trigger experiment
* \param out Pointer to array to store the measurements
* \param n Number of measurements
*/
void leading (clock_t *out, size_t n) {
srand(0);
rand();
LED (OFF);
for (size_t i =0 ; i<n ; ++i) {
clock_t t1, t2;
HAL_Delay(rand() % (MAX_WAIT_TIME + 1));
LED(ON);
t1 = clock ();
while (BTN())
;
t2 = clock ();
LED (OFF);
out[i] = CPUtime2msec(_CLOCK_DIFF(t2, t1));
}
}
/*!
* Trailing edge trigger experiment
* \param out Pointer to array to store the measurements
* \param n Number of measurements
*/
void trailing (clock_t *out, size_t n) {
srand(0);
rand();
LED (ON);
for (size_t i =0 ; i<n ; ++i) {
clock_t t1, t2;
HAL_Delay(rand() % (MAX_WAIT_TIME + 1));
LED(OFF);
t1 = clock ();
while (BTN())
;
t2 = clock ();
LED (ON);
out[i] = CPUtime2msec(_CLOCK_DIFF(t2, t1));
}
}
/*
* Main
*/
int main(void) {
clock_t times[MEASUREMENTS];
LLD_Init (SYSTICK_FREQ); // Initialize the board
// Experiment
#if MODE == MODE_LEADING_EDGE
leading (times, MEASUREMENTS);
#elif MODE == MODE_TRAILING_EDGE
trailing (times, MEASUREMENTS);
#endif
// Get statistical data
stats.average = average ((const clock_t*)times, MEASUREMENTS);
stats.median = median ((const clock_t*)times, MEASUREMENTS);
stats.std_dev = std_deviation((const clock_t*)times, MEASUREMENTS);
// Flash 10Hz to indicate the end of experiment
while (1) {
HAL_Delay(msec2CPUtime(50));
LED (ON);
HAL_Delay(msec2CPUtime(50));
LED (OFF);
}
}