#include "plc_device.h" #include "plsr_persistence.h" #include #include #include static unsigned int TestCount; #define TEST_CHECK(condition) \ do \ { \ TestCount++; \ if (!(condition)) \ { \ (void)fprintf(stderr, "FAIL line %d: %s\n", __LINE__, #condition); \ exit(EXIT_FAILURE); \ } \ } while (0) static void TestAddressMap(void) { uint16_t eventAddress; TEST_CHECK(PlsrAxisAddressMap[0].hsdRuntimeBase == 0U); TEST_CHECK(PlsrAxisAddressMap[3].hsdRuntimeBase == 12U); TEST_CHECK(PlsrAxisAddressMap[0].smPulseActiveAddress == 1000U); TEST_CHECK(PlsrAxisAddressMap[3].smDirectionAddress == 1061U); TEST_CHECK(PlsrAxisAddressMap[2].sdRuntimeBase == 1040U); TEST_CHECK(PlsrAxisAddressMap[3].eventBase == 6300U); TEST_CHECK(PlcDeviceGetEventAddress(0U, 1U, &eventAddress) == PLC_DEVICE_OK); TEST_CHECK(eventAddress == 6000U); TEST_CHECK(PlcDeviceGetEventAddress(3U, 100U, &eventAddress) == PLC_DEVICE_OK); TEST_CHECK(eventAddress == 6399U); TEST_CHECK(PlcDeviceGetEventAddress(4U, 1U, &eventAddress) == PLC_DEVICE_INVALID_ARGUMENT); TEST_CHECK(PlcDeviceGetEventAddress(0U, 0U, &eventAddress) == PLC_DEVICE_INVALID_ARGUMENT); } static void TestHsdAndPersistence(void) { uint16_t value16; int32_t value32; const int32_t firstDword = INT32_C(0x12345678); const int32_t secondDword = -INT32_C(0x1020304); PlsrPersistenceTestResetStorage(); TEST_CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceGetLastHsdLoadResult() == PLSR_PERSISTENCE_DEFAULTED); TEST_CHECK(PlcDeviceIsHsdDirty() != 0U); TEST_CHECK(PlcDeviceWriteHsdConfig(460U, 11) == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceWriteHsdConfig(539U, 0xB4E2U) == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceWriteHsdConfig(0U, 1) == PLC_DEVICE_READ_ONLY); TEST_CHECK(PlcDeviceWriteHsdConfig(459U, 1) == PLC_DEVICE_INVALID_ADDRESS); TEST_CHECK(PlcDeviceReadHsd(460U, &value16) == PLC_DEVICE_OK); TEST_CHECK(value16 == 11); TEST_CHECK(PlcDeviceReadHsd(539U, &value16) == PLC_DEVICE_OK); TEST_CHECK(value16 == 0xB4E2U); TEST_CHECK(PlcDeviceReadHsd(540U, &value16) == PLC_DEVICE_INVALID_ADDRESS); /* 32 位兼容布局:低地址=低16位,高地址=高16位。 */ TEST_CHECK(PlcDevicePublishHsdDword(0U, firstDword) == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceReadHsd(0U, &value16) == PLC_DEVICE_OK); TEST_CHECK(value16 == 0x5678U); TEST_CHECK(PlcDeviceReadHsd(1U, &value16) == PLC_DEVICE_OK); TEST_CHECK(value16 == 0x1234U); TEST_CHECK(PlcDeviceReadHsdDword(0U, &value32) == PLC_DEVICE_OK); TEST_CHECK(value32 == firstDword); TEST_CHECK(PlcDeviceReadHsdDword(1U, &value32) == PLC_DEVICE_INVALID_ADDRESS); TEST_CHECK(PlcDeviceReadHsdDword(15U, &value32) == PLC_DEVICE_INVALID_ADDRESS); TEST_CHECK(PlcDeviceCheckpointHsd() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceIsHsdDirty() == 0U); TEST_CHECK(PlcDeviceWriteHsdConfig(460U, 22) == PLC_DEVICE_OK); TEST_CHECK(PlcDevicePublishHsdDword(0U, secondDword) == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceCheckpointHsd() == PLC_DEVICE_OK); PlsrPersistenceTestCorruptNewestHsd(); TEST_CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceGetLastHsdLoadResult() == PLSR_PERSISTENCE_OK); TEST_CHECK(PlcDeviceReadHsd(460U, &value16) == PLC_DEVICE_OK); TEST_CHECK(value16 == 11); TEST_CHECK(PlcDeviceReadHsdDword(0U, &value32) == PLC_DEVICE_OK); TEST_CHECK(value32 == firstDword); } static void TestHsdDefaults(void) { uint16_t value; PlsrPersistenceTestResetStorage(); TEST_CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceGetLastHsdLoadResult() == PLSR_PERSISTENCE_DEFAULTED); /* K0(HSD460~539)出厂默认即可直接启动。 */ TEST_CHECK(PlcDeviceReadHsd(460U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 1000); /* 默认速度低16位 */ TEST_CHECK(PlcDeviceReadHsd(461U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 0); /* 默认速度高16位 */ TEST_CHECK(PlcDeviceReadHsd(462U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 100); /* 加速时间 ms */ TEST_CHECK(PlcDeviceReadHsd(463U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 100); /* 减速时间 ms */ TEST_CHECK(PlcDeviceReadHsd(466U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 0x86A0U); /* 最大速度低16位 100000 */ TEST_CHECK(PlcDeviceReadHsd(467U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 1); /* 最大速度高16位 */ TEST_CHECK(PlcDeviceReadHsd(472U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 50); /* FOLLOW 1~100 */ TEST_CHECK(PlcDeviceReadHsd(539U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 0); } static void TestHsdMetaPersistence(void) { PlsrPersistenceTestResetStorage(); TEST_CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceGetRestoredHsdPositionValid() == 0U); TEST_CHECK(PlcDeviceGetRestoredHsdLastBusy() == 0U); /* 正常停机保存:positionValid=1, lastBusy=0。 */ TEST_CHECK(PlcDeviceSetHsdCheckpointMeta(1U, 0U) == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceCheckpointHsd() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceGetRestoredHsdPositionValid() == 1U); TEST_CHECK(PlcDeviceGetRestoredHsdLastBusy() == 0U); /* 运动中掉电保存:lastBusy=1,恢复后位置不可信。 */ TEST_CHECK(PlcDeviceSetHsdCheckpointMeta(1U, 1U) == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceCheckpointHsd() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceGetRestoredHsdPositionValid() == 1U); TEST_CHECK(PlcDeviceGetRestoredHsdLastBusy() == 1U); } static void TestSfd(void) { uint16_t value; PlsrPersistenceTestResetStorage(); TEST_CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceGetLastSfdLoadResult() == PLSR_PERSISTENCE_DEFAULTED); TEST_CHECK(PlcDeviceIsSfdDirty() != 0U); TEST_CHECK(PlcDeviceReadSfd(907U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 10); TEST_CHECK(PlcDeviceReadSfd(927U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 20); TEST_CHECK(PlcDeviceReadSfd(943U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 0x0201); TEST_CHECK(PlcDeviceReadSfd(956U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 0x86A0); TEST_CHECK(PlcDeviceReadSfd(957U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 1); /* 第1套参数出厂默认可直接启动。 */ TEST_CHECK(PlcDeviceReadSfd(950U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 1000); TEST_CHECK(PlcDeviceReadSfd(951U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 0); TEST_CHECK(PlcDeviceReadSfd(952U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 100); TEST_CHECK(PlcDeviceReadSfd(962U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 50); TEST_CHECK(PlcDeviceReadSfd(1297U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 10); TEST_CHECK(PlsrPersistenceLoadSfd(NULL) == PLSR_PERSISTENCE_INVALID_ARGUMENT); TEST_CHECK(PlsrPersistenceSaveSfd(NULL) == PLSR_PERSISTENCE_INVALID_ARGUMENT); TEST_CHECK(PlcDeviceWriteSfd(900U, 123) == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceWriteSfd(1419U, 0xB456U) == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceReadSfd(900U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 123); TEST_CHECK(PlcDeviceReadSfd(1419U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 0xB456U); TEST_CHECK(PlcDeviceReadSfd(899U, &value) == PLC_DEVICE_INVALID_ADDRESS); TEST_CHECK(PlcDeviceReadSfd(1420U, &value) == PLC_DEVICE_INVALID_ADDRESS); TEST_CHECK(PlcDeviceIsSfdDirty() != 0U); TEST_CHECK(PlcDeviceSaveSfd() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceIsSfdDirty() == 0U); TEST_CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceGetLastSfdLoadResult() == PLSR_PERSISTENCE_OK); TEST_CHECK(PlcDeviceReadSfd(900U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 123); TEST_CHECK(PlcDeviceReadSfd(1419U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 0xB456U); TEST_CHECK(PlcDeviceWriteSfd(900U, 789) == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceWriteSfd(1419U, 0x9876U) == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceSaveSfd() == PLC_DEVICE_OK); PlsrPersistenceTestCorruptNewestSfd(); TEST_CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceReadSfd(900U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 123); TEST_CHECK(PlcDeviceReadSfd(1419U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 0xB456U); TEST_CHECK(PlcDeviceWriteSfd(900U, 1001) == PLC_DEVICE_OK); PlsrPersistenceTestSetSfdFault(PLSR_TEST_SFD_FAULT_ERASE); TEST_CHECK(PlcDeviceSaveSfd() == PLC_DEVICE_PERSISTENCE_ERROR); TEST_CHECK(PlcDeviceIsSfdDirty() != 0U); TEST_CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceReadSfd(900U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 123); TEST_CHECK(PlcDeviceWriteSfd(900U, 1002) == PLC_DEVICE_OK); PlsrPersistenceTestSetSfdFault(PLSR_TEST_SFD_FAULT_PROGRAM); TEST_CHECK(PlcDeviceSaveSfd() == PLC_DEVICE_PERSISTENCE_ERROR); TEST_CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceReadSfd(900U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 123); TEST_CHECK(PlcDeviceWriteSfd(900U, 1003) == PLC_DEVICE_OK); PlsrPersistenceTestSetSfdFault(PLSR_TEST_SFD_FAULT_VERIFY); TEST_CHECK(PlcDeviceSaveSfd() == PLC_DEVICE_PERSISTENCE_ERROR); TEST_CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceReadSfd(900U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 123); TEST_CHECK(PlcDeviceWriteSfd(900U, 1004) == PLC_DEVICE_OK); PlsrPersistenceTestSetSfdFault(PLSR_TEST_SFD_FAULT_BEFORE_COMMIT); TEST_CHECK(PlcDeviceSaveSfd() == PLC_DEVICE_PERSISTENCE_ERROR); TEST_CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceReadSfd(900U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 123); TEST_CHECK(PlcDevicePublishSm(0U, 1U, 0U) == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceWriteSfd(900U, 2000) == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceSaveSfd() == PLC_DEVICE_BUSY); TEST_CHECK(PlcDeviceLoadSfd() == PLC_DEVICE_BUSY); TEST_CHECK(PlcDeviceResetSfdDefaults() == PLC_DEVICE_BUSY); TEST_CHECK(PlcDevicePublishSm(0U, 0U, 0U) == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceResetSfdDefaults() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceIsSfdDirty() != 0U); TEST_CHECK(PlcDeviceReadSfd(900U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 0); TEST_CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceGetLastSfdLoadResult() == PLSR_PERSISTENCE_DEFAULTED); TEST_CHECK(PlcDeviceReadSfd(1419U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 0); TEST_CHECK(PlcDeviceReadSfd(1333U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 0x0201); } static void TestSmAndSd(void) { uint8_t state; int32_t value; TEST_CHECK(PlcDevicePublishSm(2U, 1U, 0U) == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceReadSm(1040U, &state) == PLC_DEVICE_OK); TEST_CHECK(state == 1U); TEST_CHECK(PlcDeviceReadSm(1041U, &state) == PLC_DEVICE_OK); TEST_CHECK(state == 0U); TEST_CHECK(PlcDeviceWriteSm(1040U, 0U) == PLC_DEVICE_READ_ONLY); TEST_CHECK(PlcDeviceReadSm(1042U, &state) == PLC_DEVICE_INVALID_ADDRESS); TEST_CHECK(PlcDevicePublishSd(3U, 11U, -12345) == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceReadSd(1071U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == -12345); TEST_CHECK(PlcDeviceWriteSd(1071U, 0) == PLC_DEVICE_READ_ONLY); TEST_CHECK(PlcDeviceReadSd(1012U, &value) == PLC_DEVICE_INVALID_ADDRESS); TEST_CHECK(PlcDevicePublishSd(4U, 0U, 0) == PLC_DEVICE_INVALID_ARGUMENT); TEST_CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TEST_CHECK(PlcDeviceReadSm(1040U, &state) == PLC_DEVICE_OK); TEST_CHECK(state == 0U); TEST_CHECK(PlcDeviceReadSd(1071U, &value) == PLC_DEVICE_OK); TEST_CHECK(value == 0); } int main(void) { TestAddressMap(); TestHsdAndPersistence(); TestHsdDefaults(); TestHsdMetaPersistence(); TestSfd(); TestSmAndSd(); (void)printf("PASS: %u checks\n", TestCount); return EXIT_SUCCESS; }