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:
parent
135e5d1105
commit
8ecf80b5c4
5 changed files with 138 additions and 3 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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-%)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
72
src/test/unit/time_unittest.cc
Normal file
72
src/test/unit/time_unittest.cc
Normal 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());
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue