From cfe32fe912c9f501d35f122c5c245ef36a4f3afb Mon Sep 17 00:00:00 2001 From: BillThePlatypus Date: Mon, 16 Mar 2020 14:46:08 -0600 Subject: [PATCH] Backup SRAM Unit Tests (#390) * Add backup memory functionality to testBoard * Add unit tests for recovering from hardfaults * Finish up backup sram tests --- test/state_machine_test.cpp | 113 ++++++++++++++++++++++++++++++++++++ test/test_board.cpp | 32 +++++++++- test/test_board.h | 9 ++- 3 files changed, 150 insertions(+), 4 deletions(-) diff --git a/test/state_machine_test.cpp b/test/state_machine_test.cpp index 0e8e73c5..f5b2b450 100644 --- a/test/state_machine_test.cpp +++ b/test/state_machine_test.cpp @@ -3,6 +3,7 @@ #include "rosflight.h" #include "mavlink.h" #include "test_board.h" +#include "state_manager.h" using namespace rosflight_firmware; @@ -20,6 +21,7 @@ class StateMachineTest : public ::testing::Test void SetUp() override { + board.backup_memory_clear(); rf.init(); rf.state_manager_.clear_error(rf.state_manager_.state().error_codes); // Clear All Errors to Start rf.params_.set_param_int(PARAM_MIXER, 10); @@ -389,3 +391,114 @@ TEST_F (StateMachineTest, RegainRCAfterFailsafe) EXPECT_EQ(rf.state_manager_.state().error_codes, StateManager::ERROR_NONE); EXPECT_EQ(rf.state_manager_.state().failsafe, false); } +constexpr uint32_t StateManager::BackupData::ARM_MAGIC; // C++ is weird +TEST_F (StateMachineTest, NormalBoot) +{ + board.backup_memory_clear(); + rf.state_manager_.check_backup_memory(); + EXPECT_EQ(rf.state_manager_.state().armed, false); + EXPECT_EQ(rf.state_manager_.state().error, false); + EXPECT_EQ(rf.state_manager_.state().error_codes, StateManager::ERROR_NONE); + EXPECT_EQ(rf.state_manager_.state().failsafe, false); +} +TEST_F(StateMachineTest, CrashRecoveryDisarmed) +{ + board.backup_memory_clear(); + StateManager::BackupData data; + data.arm_flag = 0; + data.error_code = 1; + data.reset_count = 1; + data.finalize(); + board.backup_memory_write(&data, sizeof(data)); + rf.state_manager_.check_backup_memory(); + EXPECT_EQ(rf.state_manager_.state().armed, false); + EXPECT_EQ(rf.state_manager_.state().error, false); + EXPECT_EQ(rf.state_manager_.state().error_codes, StateManager::ERROR_NONE); + EXPECT_EQ(rf.state_manager_.state().failsafe, false); +} +TEST_F(StateMachineTest, CrashRecoveryArmed) +{ + board.backup_memory_clear(); + StateManager::BackupData data; + data.arm_flag = StateManager::BackupData::ARM_MAGIC; + data.error_code = 1; + data.reset_count = 1; + data.finalize(); + board.backup_memory_write(&data, sizeof(data)); + rf.state_manager_.check_backup_memory(); + EXPECT_EQ(rf.state_manager_.state().armed, true); + EXPECT_EQ(rf.state_manager_.state().error, false); + EXPECT_EQ(rf.state_manager_.state().error_codes, StateManager::ERROR_NONE); + EXPECT_EQ(rf.state_manager_.state().failsafe, false); +} +TEST_F(StateMachineTest, CrashRecoveryInvalidChecksum) +{ + board.backup_memory_clear(); + StateManager::BackupData data; + data.arm_flag = StateManager::BackupData::ARM_MAGIC; + data.error_code = 1; + data.reset_count = 1; + data.finalize(); + data.checksum += 1; + board.backup_memory_write(&data, sizeof(data)); + rf.state_manager_.check_backup_memory(); + EXPECT_EQ(rf.state_manager_.state().armed, false); + EXPECT_EQ(rf.state_manager_.state().error, false); + EXPECT_EQ(rf.state_manager_.state().error_codes, StateManager::ERROR_NONE); + EXPECT_EQ(rf.state_manager_.state().failsafe, false); +} +TEST_F(StateMachineTest, CrashRecoveryInvalidArmMagic) +{ + board.backup_memory_clear(); + StateManager::BackupData data; + data.arm_flag = StateManager::BackupData::ARM_MAGIC-101; + data.error_code = 1; + data.reset_count = 1; + data.finalize(); + board.backup_memory_write(&data, sizeof(data)); + rf.state_manager_.check_backup_memory(); + EXPECT_EQ(rf.state_manager_.state().armed, false); + EXPECT_EQ(rf.state_manager_.state().error, false); + EXPECT_EQ(rf.state_manager_.state().error_codes, StateManager::ERROR_NONE); + EXPECT_EQ(rf.state_manager_.state().failsafe, false); +} +TEST_F(StateMachineTest, WriteBackupDataDisarmed) +{ + board.backup_memory_clear(); + const StateManager::BackupData::DebugInfo debug_info{1, 2, 3, 4, 5, 6, 7, 8}; + rf.state_manager_.write_backup_data(debug_info); + StateManager::BackupData data; + board.backup_memory_read(&data, sizeof(data)); + EXPECT_EQ(data.reset_count, 1); + EXPECT_EQ(data.arm_flag, 0); + EXPECT_TRUE(data.valid_checksum()); + EXPECT_EQ(data.debug.r0, debug_info.r0); + EXPECT_EQ(data.debug.r1, debug_info.r1); + EXPECT_EQ(data.debug.r2, debug_info.r2); + EXPECT_EQ(data.debug.r3, debug_info.r3); + EXPECT_EQ(data.debug.r12, debug_info.r12); + EXPECT_EQ(data.debug.lr, debug_info.lr); + EXPECT_EQ(data.debug.pc, debug_info.pc); + EXPECT_EQ(data.debug.psr, debug_info.psr); +} + +TEST_F(StateMachineTest, WriteBackupDataArmed) +{ + board.backup_memory_clear(); + rf.state_manager_.set_event(StateManager::EVENT_REQUEST_ARM); + StateManager::BackupData::DebugInfo debug_info{1, 2, 3, 4, 5, 6, 7, 8}; + rf.state_manager_.write_backup_data(debug_info); + StateManager::BackupData data; + board.backup_memory_read(&data, sizeof(data)); + EXPECT_EQ(data.reset_count, 1); + EXPECT_EQ(data.arm_flag, StateManager::BackupData::ARM_MAGIC); + EXPECT_TRUE(data.valid_checksum()); + EXPECT_EQ(data.debug.r0, debug_info.r0); + EXPECT_EQ(data.debug.r1, debug_info.r1); + EXPECT_EQ(data.debug.r2, debug_info.r2); + EXPECT_EQ(data.debug.r3, debug_info.r3); + EXPECT_EQ(data.debug.r12, debug_info.r12); + EXPECT_EQ(data.debug.lr, debug_info.lr); + EXPECT_EQ(data.debug.pc, debug_info.pc); + EXPECT_EQ(data.debug.psr, debug_info.psr); +} diff --git a/test/test_board.cpp b/test/test_board.cpp index beeb268c..298f43ca 100644 --- a/test/test_board.cpp +++ b/test/test_board.cpp @@ -68,7 +68,10 @@ void testBoard::set_imu(float *acc, float *gyro, uint64_t time_us) // setup -void testBoard::init_board() {} +void testBoard::init_board() +{ + backup_memory_clear(); +} void testBoard::board_reset(bool bootloader) {} // clock @@ -110,6 +113,33 @@ bool testBoard::imu_read(float accel[3], float *temperature, float gyro[3], uint return true; } +bool testBoard::backup_memory_read(void *dest, size_t len) +{ + bool success = true; + if(len > BACKUP_MEMORY_SIZE) + { + len = BACKUP_MEMORY_SIZE; + success = false; + } + memcpy(dest, backup_memory_, len); + return success; +} + +void testBoard::backup_memory_write(const void *src, size_t len) +{ + if(len > BACKUP_MEMORY_SIZE) + len = BACKUP_MEMORY_SIZE; + memcpy(backup_memory_, src, len); +} +void testBoard::backup_memory_clear(size_t len) +{ + memset(backup_memory_, 0, len); +} +void testBoard::backup_memory_clear() +{ + backup_memory_clear(BACKUP_MEMORY_SIZE); +} + void testBoard::imu_not_responding_error() {} bool testBoard::mag_present() { return false; } diff --git a/test/test_board.h b/test/test_board.h index d714a42c..21a968d5 100644 --- a/test/test_board.h +++ b/test/test_board.h @@ -48,6 +48,8 @@ class testBoard : public Board float acc_[3] = {0, 0, 0}; float gyro_[3] = {0, 0, 0}; bool new_imu_ = false; + static constexpr size_t BACKUP_MEMORY_SIZE{1024}; + uint8_t backup_memory_[BACKUP_MEMORY_SIZE]; public: // setup @@ -130,9 +132,10 @@ class testBoard : public Board //Backup memory void backup_memory_init() override {} - bool backup_memory_read(void *dest, size_t len) override { (void)dest; (void)len; return false; } - void backup_memory_write(const void *src, size_t len) override { (void)src; (void)len; } - void backup_memory_clear(size_t len) override { (void)len; } + bool backup_memory_read(void *dest, size_t len) override; + void backup_memory_write(const void *src, size_t len) override; + void backup_memory_clear(size_t len) override; + void backup_memory_clear(); // Not an override void set_imu(float *acc, float *gyro, uint64_t time_us); void set_rc(uint16_t *values);