mirror of
https://github.com/iNavFlight/inav.git
synced 2025-07-26 01:35:35 +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
|
// only set_BASEPRI is implemented in device library. It does always create memory barrier
|
||||||
// missing versions are implemented here
|
// 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
|
// set BASEPRI and BASEPRI_MAX register, but do not create memory barrier
|
||||||
__attribute__( ( always_inline ) ) static inline void __set_BASEPRI_nb(uint32_t basePri)
|
__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) );
|
__ASM volatile ("\tMSR basepri_max, %0\n" : : "r" (basePri) );
|
||||||
}
|
}
|
||||||
|
#endif // UNIT_TEST
|
||||||
|
|
||||||
// cleanup BASEPRI restore function, with global memory barrier
|
// cleanup BASEPRI restore function, with global memory barrier
|
||||||
static inline void __basepriRestoreMem(uint8_t *val)
|
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
|
// 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
|
// 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(), \
|
#define ATOMIC_BLOCK(prio) for ( uint8_t __basepri_save __attribute__((__cleanup__(__basepriRestoreMem))) = __get_BASEPRI(), \
|
||||||
__ToDo = __basepriSetMemRetVal(prio); __ToDo ; __ToDo = 0 )
|
__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(), \
|
#define ATOMIC_BLOCK_NB(prio) for ( uint8_t __basepri_save __attribute__((__cleanup__(__basepriRestore))) = __get_BASEPRI(), \
|
||||||
__ToDo = __basepriSetRetVal(prio); __ToDo ; __ToDo = 0 ) \
|
__ToDo = __basepriSetRetVal(prio); __ToDo ; __ToDo = 0 ) \
|
||||||
|
|
||||||
|
#endif // UNIT_TEST
|
||||||
|
|
||||||
// ATOMIC_BARRIER
|
// ATOMIC_BARRIER
|
||||||
// Create memory barrier
|
// Create memory barrier
|
||||||
// - at the beginning (all data must be reread from memory)
|
// - at the beginning (all data must be reread from memory)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "sound_beeper.h"
|
#include "sound_beeper.h"
|
||||||
#include "nvic.h"
|
#include "nvic.h"
|
||||||
#include "build/atomic.h"
|
#include "build/atomic.h"
|
||||||
|
#include "build/build_config.h"
|
||||||
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
||||||
|
@ -48,12 +49,13 @@ void registerExtiCallbackHandler(IRQn_Type irqn, extiCallbackHandlerFunc *fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// cycles per microsecond
|
// 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.
|
// 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
|
// cached value of RCC->CSR
|
||||||
uint32_t cachedRccCsrValue;
|
uint32_t cachedRccCsrValue;
|
||||||
|
|
||||||
|
#ifndef UNIT_TEST
|
||||||
void cycleCounterInit(void)
|
void cycleCounterInit(void)
|
||||||
{
|
{
|
||||||
#if defined(USE_HAL_DRIVER)
|
#if defined(USE_HAL_DRIVER)
|
||||||
|
@ -69,6 +71,7 @@ void cycleCounterInit(void)
|
||||||
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||||
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
|
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
|
||||||
}
|
}
|
||||||
|
#endif // UNIT_TEST
|
||||||
|
|
||||||
// SysTick
|
// SysTick
|
||||||
|
|
||||||
|
@ -89,8 +92,12 @@ void SysTick_Handler(void)
|
||||||
|
|
||||||
uint32_t ticks(void)
|
uint32_t ticks(void)
|
||||||
{
|
{
|
||||||
|
#ifdef UNIT_TEST
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||||
return DWT->CYCCNT;
|
return DWT->CYCCNT;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
timeDelta_t ticks_diff_us(uint32_t begin, uint32_t end)
|
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 (end - begin) / usTicks;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return system uptime in microseconds (rollover in 70minutes)
|
// Return system uptime in microseconds
|
||||||
timeUs_t microsISR(void)
|
timeUs_t microsISR(void)
|
||||||
{
|
{
|
||||||
register uint32_t ms, pending, cycle_cnt;
|
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
|
// Call microsISR() in interrupt and elevated (non-zero) BASEPRI context
|
||||||
|
|
||||||
|
#ifndef UNIT_TEST
|
||||||
if ((SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) || (__get_BASEPRI())) {
|
if ((SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) || (__get_BASEPRI())) {
|
||||||
return microsISR();
|
return microsISR();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ms = sysTickUptime;
|
ms = sysTickUptime;
|
||||||
|
@ -199,6 +208,9 @@ void delay(timeMs_t ms)
|
||||||
|
|
||||||
void failureMode(failureMode_e mode)
|
void failureMode(failureMode_e mode)
|
||||||
{
|
{
|
||||||
|
#ifdef UNIT_TEST
|
||||||
|
(void)mode;
|
||||||
|
#else
|
||||||
int codeRepeatsRemaining = 10;
|
int codeRepeatsRemaining = 10;
|
||||||
int codeFlashesRemaining;
|
int codeFlashesRemaining;
|
||||||
int shortFlashesRemaining;
|
int shortFlashesRemaining;
|
||||||
|
@ -239,4 +251,5 @@ void failureMode(failureMode_e mode)
|
||||||
#else
|
#else
|
||||||
systemResetToBootloader();
|
systemResetToBootloader();
|
||||||
#endif
|
#endif
|
||||||
|
#endif //UNIT_TEST
|
||||||
}
|
}
|
||||||
|
|
|
@ -630,6 +630,29 @@ $(OBJECT_DIR)/sensor_gyro_unittest : \
|
||||||
|
|
||||||
$(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@
|
$(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-%)
|
test: $(TESTS:%=test-%)
|
||||||
|
|
|
@ -55,6 +55,20 @@ uint8_t DMA_GetFlagStatus(uint32_t);
|
||||||
void DMA_Cmd(DMA_Channel_TypeDef*, FunctionalState );
|
void DMA_Cmd(DMA_Channel_TypeDef*, FunctionalState );
|
||||||
void DMA_ClearFlag(uint32_t);
|
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_TC_FLAG 1
|
||||||
#define WS2811_DMA_HANDLER_IDENTIFER 0
|
#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