1
0
Fork 0
mirror of https://github.com/iNavFlight/inav.git synced 2025-07-24 00:35:34 +03:00

Added time unit test

This commit is contained in:
Martin Budden 2017-02-07 10:04:18 +00:00
parent 135e5d1105
commit 8ecf80b5c4
5 changed files with 138 additions and 3 deletions

View file

@ -20,6 +20,12 @@
// only set_BASEPRI is implemented in device library. It does always create memory barrier
// missing versions are implemented here
#ifdef UNIT_TEST
static inline void __set_BASEPRI(uint32_t basePri) {(void)basePri;}
static inline void __set_BASEPRI_MAX(uint32_t basePri) {(void)basePri;}
static inline void __set_BASEPRI_nb(uint32_t basePri) {(void)basePri;}
static inline void __set_BASEPRI_MAX_nb(uint32_t basePri) {(void)basePri;}
#else
// set BASEPRI and BASEPRI_MAX register, but do not create memory barrier
__attribute__( ( always_inline ) ) static inline void __set_BASEPRI_nb(uint32_t basePri)
{
@ -30,6 +36,7 @@ __attribute__( ( always_inline ) ) static inline void __set_BASEPRI_MAX_nb(uint3
{
__ASM volatile ("\tMSR basepri_max, %0\n" : : "r" (basePri) );
}
#endif // UNIT_TEST
// cleanup BASEPRI restore function, with global memory barrier
static inline void __basepriRestoreMem(uint8_t *val)
@ -59,6 +66,10 @@ static inline uint8_t __basepriSetRetVal(uint8_t prio)
// Run block with elevated BASEPRI (using BASEPRI_MAX), restoring BASEPRI on exit. All exit paths are handled
// Full memory barrier is placed at start and exit of block
#ifdef UNIT_TEST
#define ATOMIC_BLOCK(prio) {}
#define ATOMIC_BLOCK_NB(prio) {}
#else
#define ATOMIC_BLOCK(prio) for ( uint8_t __basepri_save __attribute__((__cleanup__(__basepriRestoreMem))) = __get_BASEPRI(), \
__ToDo = __basepriSetMemRetVal(prio); __ToDo ; __ToDo = 0 )
@ -71,6 +82,8 @@ static inline uint8_t __basepriSetRetVal(uint8_t prio)
#define ATOMIC_BLOCK_NB(prio) for ( uint8_t __basepri_save __attribute__((__cleanup__(__basepriRestore))) = __get_BASEPRI(), \
__ToDo = __basepriSetRetVal(prio); __ToDo ; __ToDo = 0 ) \
#endif // UNIT_TEST
// ATOMIC_BARRIER
// Create memory barrier
// - at the beginning (all data must be reread from memory)

View file

@ -25,6 +25,7 @@
#include "sound_beeper.h"
#include "nvic.h"
#include "build/atomic.h"
#include "build/build_config.h"
#include "system.h"
@ -48,12 +49,13 @@ void registerExtiCallbackHandler(IRQn_Type irqn, extiCallbackHandlerFunc *fn)
}
// cycles per microsecond
static timeUs_t usTicks = 0;
STATIC_UNIT_TESTED timeUs_t usTicks = 0;
// current uptime for 1kHz systick timer. will rollover after 49 days. hopefully we won't care.
static volatile timeMs_t sysTickUptime = 0;
STATIC_UNIT_TESTED volatile timeMs_t sysTickUptime = 0;
// cached value of RCC->CSR
uint32_t cachedRccCsrValue;
#ifndef UNIT_TEST
void cycleCounterInit(void)
{
#if defined(USE_HAL_DRIVER)
@ -69,6 +71,7 @@ void cycleCounterInit(void)
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}
#endif // UNIT_TEST
// SysTick
@ -89,8 +92,12 @@ void SysTick_Handler(void)
uint32_t ticks(void)
{
#ifdef UNIT_TEST
return 0;
#else
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
return DWT->CYCCNT;
#endif
}
timeDelta_t ticks_diff_us(uint32_t begin, uint32_t end)
@ -98,7 +105,7 @@ timeDelta_t ticks_diff_us(uint32_t begin, uint32_t end)
return (end - begin) / usTicks;
}
// Return system uptime in microseconds (rollover in 70minutes)
// Return system uptime in microseconds
timeUs_t microsISR(void)
{
register uint32_t ms, pending, cycle_cnt;
@ -132,9 +139,11 @@ timeUs_t micros(void)
// Call microsISR() in interrupt and elevated (non-zero) BASEPRI context
#ifndef UNIT_TEST
if ((SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) || (__get_BASEPRI())) {
return microsISR();
}
#endif
do {
ms = sysTickUptime;
@ -199,6 +208,9 @@ void delay(timeMs_t ms)
void failureMode(failureMode_e mode)
{
#ifdef UNIT_TEST
(void)mode;
#else
int codeRepeatsRemaining = 10;
int codeFlashesRemaining;
int shortFlashesRemaining;
@ -239,4 +251,5 @@ void failureMode(failureMode_e mode)
#else
systemResetToBootloader();
#endif
#endif //UNIT_TEST
}

View file

@ -630,6 +630,29 @@ $(OBJECT_DIR)/sensor_gyro_unittest : \
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
$(OBJECT_DIR)/drivers/system.o : \
$(USER_DIR)/drivers/system.c \
$(USER_DIR)/drivers/system.h \
$(GTEST_HEADERS)
@mkdir -p $(dir $@)
$(CC) $(C_FLAGS) $(TEST_CFLAGS) -c $(USER_DIR)/drivers/system.c -o $@
$(OBJECT_DIR)/time_unittest.o : \
$(TEST_DIR)/time_unittest.cc \
$(USER_DIR)/drivers/system.h \
$(GTEST_HEADERS)
@mkdir -p $(dir $@)
$(CXX) $(CXX_FLAGS) $(TEST_CFLAGS) -c $(TEST_DIR)/time_unittest.cc -o $@
$(OBJECT_DIR)/time_unittest : \
$(OBJECT_DIR)/drivers/system.o \
$(OBJECT_DIR)/time_unittest.o \
$(OBJECT_DIR)/gtest_main.a
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
test: $(TESTS:%=test-%)

View file

@ -55,6 +55,20 @@ uint8_t DMA_GetFlagStatus(uint32_t);
void DMA_Cmd(DMA_Channel_TypeDef*, FunctionalState );
void DMA_ClearFlag(uint32_t);
typedef struct
{
uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
} SysTick_Type;
#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */
#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
extern SysTick_Type *SysTick;
#define WS2811_DMA_TC_FLAG 1
#define WS2811_DMA_HANDLER_IDENTIFER 0

View file

@ -0,0 +1,72 @@
/*
* This file is part of Cleanflight.
*
* Cleanflight is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Cleanflight is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>
extern "C" {
#include "common/time.h"
#include "drivers/system.h"
extern timeUs_t usTicks;
extern volatile timeMs_t sysTickUptime;
}
#include "unittest_macros.h"
#include "gtest/gtest.h"
SysTick_Type SysTickValue;
SysTick_Type *SysTick = &SysTickValue;
TEST(TimeUnittest, TestMillis)
{
sysTickUptime = 0;
EXPECT_EQ(0, millis());
sysTickUptime = 1;
EXPECT_EQ(1, millis());
}
TEST(TimeUnittest, TestMicros)
{
usTicks = 168;
SysTick->VAL = 1000 * usTicks;
sysTickUptime = 0;
EXPECT_EQ(0, micros());
sysTickUptime = 1;
EXPECT_EQ(1000, micros());
// ULONG_MAX = 4294967295
sysTickUptime = 429496; // ULONG_MAX / 1000;
EXPECT_EQ(429496000, micros());
sysTickUptime = 429497;
EXPECT_EQ(429497000, micros());
sysTickUptime = 500000;
EXPECT_EQ(500000000, micros());
sysTickUptime = 0;
SysTick->VAL = 0;
EXPECT_EQ(1000, micros());
sysTickUptime = 1;
EXPECT_EQ(2000, micros());
// ULONG_MAX = 4294967295
sysTickUptime = 429496; // ULONG_MAX / 1000;
EXPECT_EQ(429497000, micros());
sysTickUptime = 429497;
EXPECT_EQ(429498000, micros());
sysTickUptime = 500000;
EXPECT_EQ(500001000, micros());
}