From 2a64a5073efad6510eb2020881b5db4d56316487 Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Sun, 18 Feb 2024 17:26:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=8B=E4=BB=B6=E7=AD=89?= =?UTF-8?q?=E5=BE=85=E6=8C=87=E5=AE=9A=E6=97=B6=E9=97=B4BUG=EF=BC=9B?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=B0=8F=E6=96=87=E4=BB=B6=E5=AE=8C=E6=95=B4?= =?UTF-8?q?=E6=80=A7=E8=AF=BB=E5=86=99=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hardware/hardware.cpp | 12 ++-- sdk/base/plat_types.h | 7 ++- sdk/base/utils.cpp | 139 +++++++++++++++++++++++++++++++++++++++++- sdk/base/utils.h | 33 ++++++++++ ui/dev_menu.cpp | 38 ++++++++++++ ui/dev_menu.h | 95 ++++++++++++++++------------- xmake.lua | 4 +- 7 files changed, 275 insertions(+), 53 deletions(-) diff --git a/hardware/hardware.cpp b/hardware/hardware.cpp index ef6bab5..486c2e1 100644 --- a/hardware/hardware.cpp +++ b/hardware/hardware.cpp @@ -379,6 +379,8 @@ void scanner_hw::thread_image_capture(bool paper_ready) int attempt = 0; while(paper_ready && scanning_ && attempt++ < 5) { + mbev.first = -1; + mbev.second = 0; if(mb_events_.take(mbev, true, to_lifter_) && mbev.first == MOTOR_BORD_EVENT_LIFTER_READY) { @@ -386,7 +388,7 @@ void scanner_hw::thread_image_capture(bool paper_ready) break; } else - utils::to_log(LOG_LEVEL_FATAL, "Wait Lifter event(%d - 0x%08x) before scanning failed.\n", mbev.first, mbev.second); + utils::to_log(LOG_LEVEL_FATAL, "Wait Lifter event before scanning failed, get event(%d - 0x%08x).\n", mbev.first, mbev.second); motor_->start(); } if(mbev.first == MOTOR_BORD_EVENT_LIFTER_READY) @@ -477,19 +479,19 @@ void scanner_hw::thread_image_capture(bool paper_ready) // wait paper ... while(auto_scan_) { + mbev.first = -1; + mbev.second = 0; if(mb_events_.take(mbev, true)) { if(mbev.first == MOTOR_BORD_EVENT_PAPER_READY) { - motor_->start(); printf("paper ready: %d-%x\n", mbev.first, mbev.second); - mb_events_.take(mbev, true, to_lifter_); + motor_->start(); break; } - printf("motor-board event is %d\n", mbev.first); + printf("\tmotor-board event is %d\n", mbev.first); } } - printf("motor-board event is %d\n", mbev.first); } if(scanning_ && mbev.first != MOTOR_BORD_EVENT_LIFTER_READY && times == 0) diff --git a/sdk/base/plat_types.h b/sdk/base/plat_types.h index 32209bc..c490031 100644 --- a/sdk/base/plat_types.h +++ b/sdk/base/plat_types.h @@ -12,9 +12,12 @@ #define SIZE_MB(n) SIZE_KB((n) * 1024) #define SIZE_GB(n) SIZE_MB((n) * 1024) -#define SEC_2_MS(s) ((s) * 1000) -#define MSEC_2_US(ms) ((ms) * 1000) +#define USEC_2_NS(us) ((long)(us) * 1000) +#define MSEC_2_US(ms) ((long)(ms) * 1000) +#define SEC_2_MS(s) ((long)(s) * 1000) +#define MSEC_2_NS(ms) USEC_2_NS(MSEC_2_US(ms)) #define SEC_2_US(s) MSEC_2_US(SEC_2_MS(s)) +#define SEC_2_NS(s) USEC_2_NS(SEC_2_US(s)) #define MM_PER_INCH 25.4f #define IS_DOUBLE_EQUAL(a, b) fabs((a) - (b)) < .000001 diff --git a/sdk/base/utils.cpp b/sdk/base/utils.cpp index 67ae266..d3ab15d 100644 --- a/sdk/base/utils.cpp +++ b/sdk/base/utils.cpp @@ -1990,9 +1990,20 @@ bool platform_event::wait(unsigned timeout) utils::to_log(LOG_LEVEL_DEBUG, "clock_gettime failed: %d - %s\n", errno, strerror(errno)); to.tv_sec = time(nullptr); } -#endif +#endif + //*/ + to.tv_nsec += MSEC_2_NS(timeout); + to.tv_sec += to.tv_nsec / SEC_2_NS(1); + to.tv_nsec %= SEC_2_NS(1); + /*/ to.tv_sec += timeout / 1000; - to.tv_nsec += (long)((timeout % 1000) * 1000 * 1000); + to.tv_nsec += MSEC_2_NS(timeout % 1000); + if(to.tv_nsec >= SEC_2_NS(1)) + { + to.tv_sec++; + to.tv_nsec -= SEC_2_NS(1); + } + ////////*////////////////// waited = sem_timedwait(&sem_, &to) == 0; } if (log_) @@ -2350,4 +2361,126 @@ int safe_thread::stop(const char* thread_name) } return ret; -} \ No newline at end of file +} + + +//////////////////////////////////////////////////////////////////////////////////////////////// +// safe_file +safe_file::safe_file(const char* path) +{ + set_file_path(path); +} +safe_file::~safe_file() +{} + +uint32_t safe_file::checksum(const void* data, size_t bytes, uint32_t prev) +{ + uint32_t chk = prev, mask[] = {0, 0x0ff, 0x0ffff, 0x0ffffff}; + const uint32_t *d = (const uint32_t*)data; + + for(int i = 0; i < bytes / 4; ++i) + chk ^= *d++; + chk ^= *d & mask[bytes % 4]; + + return chk; +} +std::string safe_file::load_with_check(const char* file, bool ignore_lost) +{ + FILE* src = fopen(file, "rb"); + std::string cont(""); + + if(src) + { + long l = 0; + + fseek(src, 0, SEEK_END); + l = ftell(src); + fseek(src, 0, SEEK_SET); + if(l > sizeof(SFHEAD)) + { + SFHEAD head; + fread(&head, 1, sizeof(head), src); + if(head.len == l - sizeof(head)) + { + char buf[256] = {0}; + int r = fread(buf, 1, sizeof(buf), src); + while(r > 0) + { + cont += std::string(buf, r); + r = fread(buf, 1, sizeof(buf), src); + } + + uint32_t chk = checksum(&head, sizeof(head)); + + chk = checksum(cont.c_str(), cont.length(), chk); + if(chk) + { + utils::to_log(LOG_LEVEL_FATAL, "Checksum(%08x) of safe_file(%s) failed!\n", chk, file); + cont = ""; + } + else + { + iotimes_ = head.iotimes; + } + } + else + { + utils::to_log(LOG_LEVEL_FATAL, "safe_file(%s) length(%d) is mismatched(%d)!\n", file, (int)l, head.len); + } + } + else + { + utils::to_log(LOG_LEVEL_FATAL, "safe_file(%s) length(%d) is too small!\n", file, (int)l); + } + fclose(src); + } + else if(!ignore_lost) + { + utils::to_log(LOG_LEVEL_FATAL, "open safe_file(%s) failed: %d(%s).\n", file, errno, strerror(errno)); + } + + return std::move(cont); +} + +void safe_file::set_file_path(const char* path) +{ + path_ = path ? path : ""; + iotimes_ = 0; +} +std::string safe_file::load(void) +{ + std::string cont(load_with_check((path_ + tmp_appendix_).c_str(), true)); + + if(cont.empty()) + cont = load_with_check(path_.c_str(), false); + + return std::move(cont); +} +int safe_file::save(const void* data, uint16_t bytes) +{ + // io time ... + if(iotimes_ == 0) + { + load(); + } + + SFHEAD head; + FILE *dst = nullptr; + + head.chksum = 0; + head.iotimes = ++iotimes_; + head.len = bytes; + head.time = time(nullptr); + head.chksum = checksum(&head, sizeof(head)); + head.chksum = checksum(data, bytes, head.chksum); + + dst = fopen((path_ + tmp_appendix_).c_str(), "wb"); + if(!dst) + return errno; + + fwrite(&head, 1, sizeof(head), dst); + fwrite(data, 1, bytes, dst); + fclose(dst); + + return rename((path_ + tmp_appendix_).c_str(), path_.c_str()); +} diff --git a/sdk/base/utils.h b/sdk/base/utils.h index 2562157..ac3c575 100644 --- a/sdk/base/utils.h +++ b/sdk/base/utils.h @@ -482,3 +482,36 @@ public: int start(std::function f, const char* thread_name, void* addr = nullptr); int stop(const char* thread_name); }; + +// Purpose: safe file ensure the integrity of small data files +// +// Format: (uint16_t)raw data len + (uint32_t)checksum + raw data +// +// Flow: when save, write into file 'name.new' first, and rename to 'name' at last +// when read, check 'name.new' first, and open name if '.new' not exists +class safe_file +{ + typedef struct _sf_head // ensure this struct size be multiple of size uint32_t + { + uint32_t chksum; + uint32_t time; + uint64_t len : 16; + uint64_t iotimes : 48; + }SFHEAD, *LPSFHEAD; + + const std::string tmp_appendix_ = ".new"; + std::string path_; + uint64_t iotimes_ = 0; + + uint32_t checksum(const void* data, size_t bytes, uint32_t prev = 0); + std::string load_with_check(const char* file, bool ignore_lost); + +public: + safe_file(const char* path); + ~safe_file(); + +public: + void set_file_path(const char* path); + std::string load(void); + int save(const void* data, uint16_t bytes); +}; diff --git a/ui/dev_menu.cpp b/ui/dev_menu.cpp index 0b3757b..26e6afa 100644 --- a/ui/dev_menu.cpp +++ b/ui/dev_menu.cpp @@ -403,6 +403,10 @@ static uint8_t qiaoting[] = {128, 32 } }; +#define TEST_PLATFORM_EVENT +#ifdef TEST_PLATFORM_EVENT +platform_event to__("to"); +#endif ui_mgr::ui_mgr() : disp_data_("lcd-msg") { utils::init_log(LOG_TYPE_FILE); @@ -428,10 +432,40 @@ ui_mgr::ui_mgr() : disp_data_("lcd-msg") auto display = [this](void) -> void { +#ifdef TEST_PLATFORM_EVENT + printf("\tdisplay thread starting, sleep 3000ms ...\n"); + std::this_thread::sleep_for(std::chrono::milliseconds(3000)); + printf("\tdisplay thread trigger event ...\n"); + to__.trigger(); +#endif thread_display(); }; +#ifdef TEST_PLATFORM_EVENT + to__.enable_log(false); +#endif disp_thrd_.start(display, "thread_display"); +#ifdef TEST_PLATFORM_EVENT +// display thread starting, sleep 3000ms ... +// [2024-02-18 08:01:54.349173] try wait 001: Failure +// [2024-02-18 08:01:54.849311] try wait 002: Failure +// [2024-02-18 08:01:55.349411] try wait 003: Failure +// [2024-02-18 08:01:55.849550] try wait 004: Failure +// [2024-02-18 08:01:56.349645] try wait 005: Failure +// display thread trigger event ... +// [2024-02-18 08:01:56.849441] try wait 006: OK +// [2024-02-18 08:01:57.349550] try wait 007: Failure +// [2024-02-18 08:01:57.849659] try wait 008: Failure + int up = 10000; + for(int i = 0; i < up; ++i) + { + bool wait = to__.wait(500); + printf("[%s] try wait %03d: %s\n", utils::format_current_time().c_str(), i + 1, wait ? "OK" : "Failure"); + if(wait) + up = i + 3; + } +#endif + auto statu = [this](devui::LPMSGSTREAM pack) -> void { if(pack->msg == devui::UI_STATUS_SCANNING) @@ -462,6 +496,10 @@ ui_mgr::ui_mgr() : disp_data_("lcd-msg") disp_data_.save(dd, true); } } + else + { + perm_data_->save(); + } } else if(pack->msg == devui::UI_STATUS_PAPER_CNT) { diff --git a/ui/dev_menu.h b/ui/dev_menu.h index 84a662a..2b05e67 100644 --- a/ui/dev_menu.h +++ b/ui/dev_menu.h @@ -136,40 +136,42 @@ class ui_mgr : public refer utils::create_folder(root_.c_str()); root_ += PATH_SEPARATOR; - char buf[1024] = {0}, *ptr = buf; - FILE *src = fopen((root_ + his_name_).c_str(), "rb"); - int len = 0; + safe_file file((root_ + his_name_).c_str()); + std::string cont(file.load()); + char *ptr = &cont[0]; LPSPEEDTM pspt = nullptr; - if(src) + if(!cont.empty()) { - len = fread(buf, 1, sizeof(buf), src); - fclose(src); - history_cnt_ = *(uint64_t*)buf; - - len -= sizeof(history_cnt_); - ptr = buf + sizeof(history_cnt_); + history_cnt_ = *(uint64_t*)ptr; + ptr += sizeof(history_cnt_); pspt = (LPSPEEDTM)ptr; - for(int i = 0; i < len / sizeof(*pspt); ++i) + for(int i = 0; i < (cont.length() - sizeof(history_cnt_)) / sizeof(*pspt); ++i) { TIMES t = {0}; t.history = pspt[i].ms; speed_times_[pspt[i].speed] = t; } } - - src = fopen((root_ + rol_name_).c_str(), "rb"); - if(src) + else { - memset(buf, 0, sizeof(buf)); - len = fread(buf, 1, sizeof(buf), src); - fclose(src); - roller_cnt_ = *(uint32_t*)buf; + // test data: + TIMES t = {0}; - len -= sizeof(roller_cnt_); - ptr = buf + sizeof(roller_cnt_); + history_cnt_ = 711; + t.history = 0x65642; + speed_times_[816] = t; + } + + file.set_file_path((root_ + rol_name_).c_str()); + cont = file.load(); + if(!cont.empty()) + { + ptr = &cont[0]; + roller_cnt_ = *(uint32_t*)ptr; + ptr += sizeof(roller_cnt_); pspt = (LPSPEEDTM)ptr; - for(int i = 0; i < len / sizeof(*pspt); ++i) + for(int i = 0; i < (cont.length() - sizeof(roller_cnt_)) / sizeof(*pspt); ++i) { if(speed_times_.count(pspt[i].speed)) { @@ -178,11 +180,17 @@ class ui_mgr : public refer else { TIMES t = {0}; - t.roller = pspt[i].ms; + t.history = t.roller = pspt[i].ms; speed_times_[pspt[i].speed] = t; } } } + else + { + // test data: + roller_cnt_ = 257; + speed_times_[816].roller = 0x2e54b; + } } protected: @@ -209,6 +217,11 @@ class ui_mgr : public refer speed_times_[speed_].roller += run_ms; if(hiscnt) *hiscnt = history_cnt_; + if(adden_ > 10) + { + save(); + adden_ = 0; + } return roller_cnt_; } @@ -217,6 +230,8 @@ class ui_mgr : public refer roller_cnt_ = 0; for(auto& v: speed_times_) v.second.roller = 0; + + save(); return roller_cnt_; } @@ -231,33 +246,31 @@ class ui_mgr : public refer } void save(void) { - FILE *dst = fopen((root_ + his_name_).c_str(), "wb"); - if(dst) - { - fwrite(&history_cnt_, 1, sizeof(history_cnt_), dst); - for(auto& v: speed_times_) - { - SPEEDTM stm = {0}; - stm.speed = v.first; - stm.ms = v.second.history; - fwrite(&stm, 1, sizeof(stm), dst); - } - fclose(dst); - } + safe_file file((root_ + his_name_).c_str()); + std::string cont((char*)&history_cnt_, sizeof(history_cnt_)); - dst = fopen((root_ + rol_name_).c_str(), "wb"); - if(dst) + for(auto& v: speed_times_) { - fwrite(&roller_cnt_, 1, sizeof(roller_cnt_), dst); - for(auto& v: speed_times_) + SPEEDTM stm = {0}; + stm.speed = v.first; + stm.ms = v.second.history; + cont += std::string((char*)&stm, sizeof(stm)); + } + file.save(cont.c_str(), cont.length()); + + cont = std::string((char*)&roller_cnt_, sizeof(roller_cnt_)); + for(auto& v: speed_times_) + { + if(v.second.roller) { SPEEDTM stm = {0}; stm.speed = v.first; stm.ms = v.second.roller; - fwrite(&stm, 1, sizeof(stm), dst); + cont += std::string((char*)&stm, sizeof(stm)); } - fclose(dst); } + file.set_file_path((root_ + rol_name_).c_str()); + file.save(cont.c_str(), cont.length()); } }; refer_guard perm_data_; diff --git a/xmake.lua b/xmake.lua index cb386f9..4f3d051 100644 --- a/xmake.lua +++ b/xmake.lua @@ -60,8 +60,8 @@ add_packagedirs("sdk") add_defines("BUILD_AS_DEVICE") add_defines("VER_MAIN=2") add_defines("VER_FAMILY=200") -add_defines("VER_DATE=20240208") -add_defines("VER_BUILD=2") +add_defines("VER_DATE=20240218") +add_defines("VER_BUILD=20") target("conf") set_kind("phony")