diff --git a/src/logging/logging.c b/src/logging/logging.c index c181065e4..13b5caae7 100644 --- a/src/logging/logging.c +++ b/src/logging/logging.c @@ -8,6 +8,16 @@ // Commands register, execution API and cmd tokenizer #include "../cmnds/cmd_public.h" +#if ENABLE_LITTLEFS && ENABLE_LOG2LFS +#include "../littlefs/our_lfs.h" +#include "../new_cfg.h" // we will use CFG_Set_log2lfs(); +// end "uptime" if log2lfs is enabled +// not needed if logging only on startup +//static int log2lfs_end = 0; +// uptime counter - seconds since boot to know how long to logg to LFS +extern int g_secondsElapsed; +#endif + #if PLATFORM_BEKEN_NEW #include "uart.h" #include "arm_arch.h" @@ -16,6 +26,7 @@ extern uint8_t g_StartupDelayOver; + int g_loglevel = LOG_INFO; // default to info unsigned int logfeatures = ( (1 << 0) | @@ -128,6 +139,7 @@ static struct tag_logMemory { int tailserial; int tailtcp; int tailhttp; + int taillfs; SemaphoreHandle_t mutex; } logMemory; @@ -224,10 +236,44 @@ SetFlag 31 1 logPort 1 */ +#if ENABLE_LITTLEFS && ENABLE_LOG2LFS +// forward declaration - we'll need function here +static void LOG_LFS_StartThread(const char *prefix); + +static commandResult_t CMD_logStartup2lfs(const void* context, const char* cmd, const char* args, int cmdFlags) { + Tokenizer_TokenizeString(args, 0); + uint8_t secs = (uint8_t)Tokenizer_GetArgIntegerDefault(0,10); + if (secs > LOG2LFS_MAX_SECONDS) { + ADDLOG_ERROR(LOG_FEATURE_LFS, "log2lfs: Seconds out of range. Set seconds to maximum value %i",LOG2LFS_MAX_SECONDS); + secs = LOG2LFS_MAX_SECONDS; + } + uint8_t repeats = (uint8_t)Tokenizer_GetArgIntegerDefault(1,1); + if (repeats > LOG2LFS_MAX_REPEATS) { + ADDLOG_ERROR(LOG_FEATURE_LFS, "log2lfs: Repeats out of range. Set repeats to maximum value %i",LOG2LFS_MAX_REPEATS); + repeats = LOG2LFS_MAX_REPEATS; + } + CFG_Set_log2lfs(LOG2LFS_ENCODE(secs,repeats)); + CFG_Save_IfThereArePendingChanges(); + return CMD_RES_OK; +} + +void initLog2LFS(void){ + // since logging will be called beforeflash config is initialized, we can get + // information, if we should log startup to LFS, not at init + // so we need a separate function to set this up if logStartup2lfs is configureded + // if so, g_log2lfs will hold the numbers of seconds to log to LFS + // we will calculate "end time" for this here + if (g_log2lfs >0 && g_secondsElapsed < g_log2lfs) { +// not needed if logging only on startup +// log2lfs_end = g_secondsElapsed + g_log2lfs; + LOG_LFS_StartThread("startupLog"); + } +} +#endif static void initLog(void) { bk_printf("Entering initLog()...\r\n"); - logMemory.head = logMemory.tailserial = logMemory.tailtcp = logMemory.tailhttp = 0; + logMemory.head = logMemory.tailserial = logMemory.tailtcp = logMemory.tailhttp = logMemory.taillfs = 0; logMemory.mutex = xSemaphoreCreateMutex(); initialised = 1; startSerialLog(); @@ -254,6 +300,21 @@ static void initLog(void) //cmddetail:"fn":"log_command","file":"logging/logging.c","requires":"", //cmddetail:"examples":""} CMD_RegisterCommand("logdelay", log_command, NULL); +#if ENABLE_LITTLEFS && ENABLE_LOG2LFS +// for now, no logging to lfs during normal operation +// don't simply comment out the block, but every line to +// make sure, cmddetails are alos commented out - else they would be included to docs later +// //cmddetail:{"name":"log2lfs","args":"[Seconds - default: 10s]", +// //cmddetail:"descr":"Start logging to LittleFS. Value is the number of seconds log lines are appended to startupLog_N.txt on LFS. Set to 0 to disable/stop a running logging.", +// //cmddetail:"fn":"log_command","file":"logging/logging.c","requires":"", +// //cmddetail:"examples":"log2lfs 10"} +// CMD_RegisterCommand("log2lfs", log_command, NULL); + //cmddetail:{"name":"logStartup2lfs","args":"[Seconds - default: 10s] [repetitions - default 1]", + //cmddetail:"descr":"Enable startup logging to LittleFS. Value is the number of seconds from boot during which log lines are appended to startupLog_N.txt on LFS. Set to 0 to disable.\nIf you want to log severals startups, use optional repeats argument", + //cmddetail:"fn":"log_command","file":"logging/logging.c","requires":"", + //cmddetail:"examples":"logStartup2lfs 15"} + CMD_RegisterCommand("logStartup2lfs", CMD_logStartup2lfs, NULL); +#endif #if PLATFORM_BEKEN || PLATFORM_LN882H //cmddetail:{"name":"logport","args":"[Index]", //cmddetail:"descr":"Allows you to change log output port. On Beken, the UART1 is used for flashing and for TuyaMCU/BL0942, while UART2 is for log. Sometimes it might be easier for you to have log on UART1, so now you can just use this command like backlog uartInit 115200; logport 1 to enable logging on UART1..", @@ -432,6 +493,10 @@ void addLogAdv(int level, int feature, const char* fmt, ...) { logMemory.tailhttp = (logMemory.tailhttp + 1) % LOGSIZE; } + if (logMemory.taillfs == logMemory.head) + { + logMemory.taillfs = (logMemory.taillfs + 1) % LOGSIZE; + } } if (taken == pdTRUE) { @@ -552,6 +617,294 @@ static int getHttp(char* buff, int buffsize) { //printf("got tcp: %d:%s\r\n", len,buff); return len; } +#if ENABLE_LITTLEFS && ENABLE_LOG2LFS + +// Startup log filename, chosen when the thread first opens the file. +static char g_lfsLogName[48] = {0}; +static const char *g_lfsLogPrefix = "startupLog"; // default name + +// Continuous-drain thread: mirrors log_serial_thread / log_client_thread. +// Waits for LFS to mount, then drains logMemory.taillfs into the file in +// small chunks until the capture window closes. Writing in a thread means +// flash erase/program never blocks the main system or IRQ watchdog. +// lfs_file_t is in a local struct on the heap to keep the thread stack lean. + +// how much to write in one chunk +#define LOG2LFS_WRITE_CHUNK 128 + +// only needed for logging during operation. +// static volatile int g_log2lfs_running = 0; // 1 while thread is alive + +// after sucesfull logging, set new value for the next start: +// set to 0, if this was the only/last logging configured +// else set new value for next start (decrease repeat count by 1) +void log2lfs_set_next_startup(){ + uint8_t act = CFG_Get_log2lfs(); + // shall we repeat logging? + // then set value for next startup + if (LOG2LFS_REPEATS(act) > 1) { + CFG_Set_log2lfs(LOG2LFS_DECREASE_REPEAT(act)); + } else { + // not repeating? Set to 0 for next startup + CFG_Set_log2lfs(0); + } +} + + +// two versions of static void log2lfs_thread(beken_thread_arg_t arg) follow +// Actually I used the smaller second one - no size checking, just write and +// hit the wall, if FS is full. We need to stop then anyway + +/* +// fair and nice: +// check for remaining LFS size and try not to reach an error while writing, but stop before +// logging to LFS will fill it up +// checking for free space is "expensive" +// so check for remaining space before we start and calculate +// actual filling of fs (assuming no other thread will fill lfs at the same time). +// If we get "near" a full fs, recheck, just in case +// This define will declare, what is "nearly" full +#define LOG2LFS_SPACE_RECHECK_THRESHOLD 1024 + +// Returns free bytes on LFS, or -1 on error. +static int LOG_LFS_FreeBytes(void) +{ + lfs_ssize_t used = lfs_fs_size(&lfs); + if (used < 0) return -1; + extern struct lfs_config cfg; + return (int)((cfg.block_count - (lfs_size_t)used) * cfg.block_size); +} + + +static void log2lfs_thread(beken_thread_arg_t arg) +{ + char chunk[LOG2LFS_WRITE_CHUNK]; + lfs_file_t *lf = os_malloc(sizeof(lfs_file_t)); + int file_open = 0; + int free_bytes = 0; + int n; + + if (!lf) { + ADDLOG_ERROR(LOG_FEATURE_LFS, "log2lfs: could not allocate lfs_file_t"); + goto done; + } + + // Wait for LFS to become available before opening the file. + while (!lfs_present()) { + if (g_secondsElapsed > log2lfs_end) + goto done; // window closed before LFS ever mounted + rtos_delay_milliseconds(100); + } + + // Check space once before opening the file — keep free_bytes for later tracking. + free_bytes = LOG_LFS_FreeBytes(); + if (free_bytes < LOG2LFS_WRITE_CHUNK) { + ADDLOG_ERROR(LOG_FEATURE_LFS, "log2lfs: LFS full (%d bytes free), aborting", free_bytes); + goto done; + } + ADDLOG_INFO(LOG_FEATURE_LFS, "log2lfs: %d bytes free on LFS", free_bytes); + + // Choose filename now that LFS is mounted (dir scan sees real files). + // Use wall-clock timestamp if available, otherwise incrementing counter. + if (TIME_IsTimeSynced()) { + uint32_t tempt = TIME_GetCurrentTime(); + snprintf(g_lfsLogName, sizeof(g_lfsLogName), "%s_%s.txt", g_lfsLogPrefix, TS2STR(tempt, TIME_FORMAT_SHORT)); + } else { + // Fallback: scan for highest existing counter and increment it. + int highest = -1; + unsigned int cnt; + char t = '0'; + lfs_dir_t dir; + struct lfs_info info; + char scanfmt[32]; + // since we might have some "timestamp" files, dont use date as number - check after the number there's the '.' from ".txt" + snprintf(scanfmt, sizeof(scanfmt), "%s_%%u%%ctxt", g_lfsLogPrefix); + if (lfs_dir_open(&lfs, &dir, "/") >= 0) { + while (lfs_dir_read(&lfs, &dir, &info) > 0) { + t = '0'; + if (info.type == LFS_TYPE_REG && + sscanf(info.name, scanfmt, &cnt, &t) == 2 && + t == '.' && + cnt > highest) { + highest = cnt; + } + } + lfs_dir_close(&lfs, &dir); + } + snprintf(g_lfsLogName, sizeof(g_lfsLogName), "%s_%d.txt", g_lfsLogPrefix, highest + 1); + } + + if (lfs_file_open(&lfs, lf, g_lfsLogName, LFS_O_RDWR | LFS_O_CREAT) < 0) { + ADDLOG_ERROR(LOG_FEATURE_LFS, "log2lfs: could not open %s", g_lfsLogName); + goto done; + } + file_open = 1; + lfs_file_seek(&lfs, lf, 0, LFS_SEEK_END); + ADDLOG_INFO(LOG_FEATURE_LFS, "log2lfs: writing to %s", g_lfsLogName); + + // Drain taillfs continuously until the capture window closes. + while (g_secondsElapsed <= log2lfs_end) { + while ((n = getData(chunk, sizeof(chunk), &logMemory.taillfs)) > 0) { + if (lfs_file_write(&lfs, lf, chunk, n) < 0) { + ADDLOG_ERROR(LOG_FEATURE_LFS, "log2lfs: write error, stopping"); + goto done; + } + free_bytes -= n; + // Only re-check actual FS space when our estimate gets low — + // avoids calling lfs_fs_size() on every chunk. Re-sync also + // catches any concurrent LFS writes from other threads. + if (free_bytes < LOG2LFS_SPACE_RECHECK_THRESHOLD) { + free_bytes = LOG_LFS_FreeBytes(); + if (free_bytes < LOG2LFS_WRITE_CHUNK) { + ADDLOG_ERROR(LOG_FEATURE_LFS, "log2lfs: LFS full (%d bytes free), stopping", free_bytes); + goto done; + } + } + } + rtos_delay_milliseconds(200); // poll interval — keeps watchdog fed + } + + // Final drain: capture any lines logged in the last poll interval. + while ((n = getData(chunk, sizeof(chunk), &logMemory.taillfs)) > 0) + lfs_file_write(&lfs, lf, chunk, n); + +done: + if (file_open) { + lfs_file_close(&lfs, lf); + ADDLOG_INFO(LOG_FEATURE_LFS, "log2lfs: done, file closed"); + } + os_free(lf); + g_log2lfs = 0; + g_log2lfs_running = 0; + rtos_delete_thread(NULL); +} +*/ + +// simpler but "brute force": Just write until we finished writing --- +// or writing returns an error if we filled up the whole remaining LFS +static void log2lfs_thread(beken_thread_arg_t arg) +{ + char chunk[LOG2LFS_WRITE_CHUNK]; + lfs_file_t *lf = os_malloc(sizeof(lfs_file_t)); + int file_open = 0; + int n; + + if (!lf) { + ADDLOG_ERROR(LOG_FEATURE_LFS, "log2lfs: could not allocate lfs_file_t"); + goto done; + } + + // Wait for LFS to become available before opening the file. + while (!lfs_present()) { +// not needed if logging only on startup +// if (g_secondsElapsed > log2lfs_end) + if (g_secondsElapsed > g_log2lfs) + goto done; // logging window closed before LFS ever mounted + rtos_delay_milliseconds(100); + } + +/* +// only for logging durlig operation; quite sure there's no valid time startup + // Choose filename now that LFS is mounted (dir scan sees real files). + // Use timestamp if time is available, otherwise incrementing counter. + if (TIME_IsTimeSynced()) { + uint32_t tempt = TIME_GetCurrentTime(); + snprintf(g_lfsLogName, sizeof(g_lfsLogName), "%s_%s.txt", g_lfsLogPrefix, TS2STR(tempt, TIME_FORMAT_SHORT)); + } else +*/ + { + int highest = -1; + unsigned int cnt; + // caution: we made cnt an unsigned int, so it won't accept "negative numbers" in sscanf (using %u instead of %d) + // to compare them, make sure to cast cnt to int + // else highest will be casted as unsigned, resulting in a huge number if it was negative!!! + char t = '0'; + lfs_dir_t dir; + struct lfs_info info; + char scanfmt[32]; + // since we might have some "timestamp" files, dont use date as number - check after the number there's the '.' from ".txt" + snprintf(scanfmt, sizeof(scanfmt), "%s_%%u%%ctxt", g_lfsLogPrefix); + if (lfs_dir_open(&lfs, &dir, "/") >= 0) { + while (lfs_dir_read(&lfs, &dir, &info) > 0) { + t = '0'; + if (info.type == LFS_TYPE_REG && + sscanf(info.name, scanfmt, &cnt, &t) == 2 && + t == '.' && + (int)cnt > highest) { + highest = (int)cnt; + } + } + lfs_dir_close(&lfs, &dir); + } + snprintf(g_lfsLogName, sizeof(g_lfsLogName), "%s_%d.txt", g_lfsLogPrefix, highest + 1); + } + + if (lfs_file_open(&lfs, lf, g_lfsLogName, LFS_O_RDWR | LFS_O_CREAT) < 0) { + ADDLOG_ERROR(LOG_FEATURE_LFS, "log2lfs: could not open %s", g_lfsLogName); + goto done; + } + file_open = 1; + lfs_file_seek(&lfs, lf, 0, LFS_SEEK_END); + ADDLOG_INFO(LOG_FEATURE_LFS, "log2lfs: writing to %s", g_lfsLogName); + + // Drain taillfs continuously until the capture window closes. +// not needed if logging only on startup +// while (g_secondsElapsed <= log2lfs_end) { + while (g_secondsElapsed <= g_log2lfs) { + while ((n = getData(chunk, sizeof(chunk), &logMemory.taillfs)) > 0) { + if (lfs_file_write(&lfs, lf, chunk, n) < 0) { + ADDLOG_ERROR(LOG_FEATURE_LFS, "log2lfs: write error, stopping"); + goto done; + } + } + rtos_delay_milliseconds(200); + } + + // Final drain: capture any lines logged in the last poll interval. + while ((n = getData(chunk, sizeof(chunk), &logMemory.taillfs)) > 0) + if (lfs_file_write(&lfs, lf, chunk, n) < 0) + break; + +done: + if (file_open) { + lfs_file_close(&lfs, lf); + ADDLOG_INFO(LOG_FEATURE_LFS, "log2lfs: done, file closed"); + } + os_free(lf); + log2lfs_set_next_startup(); + g_log2lfs = 0; +// only needed for logging during operation. +// g_log2lfs_running = 0; + rtos_delete_thread(NULL); +} + +static void LOG_LFS_StartThread(const char *prefix) +{ +/* +// only needed for logging during operation. Else there will be exactly one +// thread after startup. + g_lfsLogPrefix = prefix; + if (g_log2lfs_running == 1) { + // Thread already active — use the new g_log2lfs_end value. + ADDLOG_INFO(LOG_FEATURE_LFS, "log2lfs: extending window to %d s", g_log2lfs); + return; + } + g_log2lfs_running = 1; +*/ + if (rtos_create_thread(NULL, BEKEN_APPLICATION_PRIORITY, + "log2lfs", + (beken_thread_function_t)log2lfs_thread, + 0x800, + (beken_thread_arg_t)0) != kNoErr) { + ADDLOG_ERROR(LOG_FEATURE_LFS, "log2lfs: could not create thread"); +// only needed for logging during operation. +// g_log2lfs_running = 0; + } else { + ADDLOG_DEBUG(LOG_FEATURE_LFS, "log2lfs: created thread"); + } +} + +#endif // ENABLE_LITTLEFS && ENABLE_LOG2LFS void startLogServer() { #if WINDOWS @@ -860,7 +1213,34 @@ commandResult_t log_command(const void* context, const char* cmd, const char* ar result = CMD_RES_OK; break; } - +/* +// for now, only implement logging at startup, not during operation +#if ENABLE_LITTLEFS && ENABLE_LOG2LFS + if (!stricmp(cmd, "log2lfs")) { + int res, secs; + res = sscanf(args, "%d", &secs); + if (res != 1 || secs < 0) secs = 10; // default 10 secs + g_log2lfs = secs; + if (secs > 0) { + log2lfs_end = g_secondsElapsed + g_log2lfs; + ADDLOG_INFO(LOG_FEATURE_LFS, "log2lfs: capturing for %d s (uptime now %d s) -- g_log2lfs_running=%i", + g_log2lfs, g_secondsElapsed, g_log2lfs_running); + if (!g_log2lfs_running) { + // Snap taillfs to head so we capture only from this moment. + BaseType_t taken = xSemaphoreTake(logMemory.mutex, 100); + logMemory.taillfs = logMemory.head; + if (taken == pdTRUE) xSemaphoreGive(logMemory.mutex); + g_lfsLogName[0] = '\0'; + } + LOG_LFS_StartThread("messageLog"); + } else { + ADDLOG_INFO(LOG_FEATURE_LFS, "log2lfs disabled"); + } + result = CMD_RES_OK; + break; + } +#endif // ENABLE_LITTLEFS && ENABLE_LOG2LFS +*/ } while (0); return result; diff --git a/src/logging/logging.h b/src/logging/logging.h index 3d73c7a1a..bf69a6970 100644 --- a/src/logging/logging.h +++ b/src/logging/logging.h @@ -38,6 +38,30 @@ extern char *logfeaturenames[]; extern volatile int direct_serial_log; + +#if ENABLE_LITTLEFS && ENABLE_LOG2LFS +// LFS (startup) logging +#include "../driver/drv_deviceclock.h" // for TIME_IsTimeSynced() / TIME_GetCurrentTime() +// To enable optional clock timestamp for the LFS startup log filename if clock is set. +#include "../libraries/obktime/obktime.h" // for formatting time as str (TS2STR and TIME_FORMAT_SHORT) + +// Set to 0 to disable, or N to log for the first N seconds of uptime. +// The log is written to "startupLog_.txt" on LittleFS. +// Controlled at runtime with the "log2lfs" command. +extern uint8_t g_log2lfs; +#define LOG2LFS_MAX_SECONDS 30 +#define LOG2LFS_BASE (uint8_t)(LOG2LFS_MAX_SECONDS + 1) +#define LOG2LFS_MAX_REPEATS (uint8_t)((255 / LOG2LFS_BASE) + 1 ) // adding 0 will mean once / one repetition + +// some helpers +#define LOG2LFS_SECONDS(X) (uint8_t)(X % LOG2LFS_BASE) +#define LOG2LFS_REPEATS(X) (uint8_t)(X / LOG2LFS_BASE + 1) +#define LOG2LFS_ENCODE(S,R) (uint8_t)(S + ((R > 1) ? LOG2LFS_BASE * (R - 1) : 0)) +#define LOG2LFS_DECREASE_REPEAT(X) (uint8_t)(X >= (LOG2LFS_BASE) ? X - LOG2LFS_BASE : X) + + +#endif + typedef enum logType_e { LOGTYPE_NONE, LOGTYPE_DIRECT, diff --git a/src/new_cfg.c b/src/new_cfg.c index 7556cfc8d..c774ec38b 100644 --- a/src/new_cfg.c +++ b/src/new_cfg.c @@ -789,6 +789,16 @@ uint32_t CFG_GetLFS_Size() { } return size; } +// time to write log messages to lfs (0=disabled) +uint8_t CFG_Get_log2lfs() { + return g_cfg.log2lfs; +} +void CFG_Set_log2lfs(uint8_t value) { + if(g_cfg.log2lfs != value) { + g_cfg.log2lfs = value; + g_cfg_pendingChanges++; + } +} #endif #if MQTT_USE_TLS diff --git a/src/new_cfg.h b/src/new_cfg.h index 421051b06..c381d558a 100644 --- a/src/new_cfg.h +++ b/src/new_cfg.h @@ -96,6 +96,8 @@ void CFG_SetWebPassword(const char *s); #if ENABLE_LITTLEFS void CFG_SetLFS_Size(uint32_t value); uint32_t CFG_GetLFS_Size(); +uint8_t CFG_Get_log2lfs(); +void CFG_Set_log2lfs(uint8_t value); #endif #if MQTT_USE_TLS diff --git a/src/new_pins.h b/src/new_pins.h index 569ced595..898e15962 100644 --- a/src/new_pins.h +++ b/src/new_pins.h @@ -1480,6 +1480,11 @@ typedef struct ledRemap_s { // We should not worry about flash memory wear in this case. // The saved-every-reboot values are stored elsewhere // (i.e. saved channel states, reboot counter?) + +// add more comments about actual "offset" of an entry +// especially after "pins" - which has different size for different platforms +// --> all offsets differ up to unusedSectorAB which almost brings all back +// (afterwars we only have to distinguish 2 groups which differ by "only" 2 bytes) typedef struct mainConfig_s { byte ident0; byte ident1; @@ -1515,6 +1520,7 @@ typedef struct mainConfig_s { // at offs 0x298 char webappRoot[64]; // TODO? + // 0x2d8 byte mac[6]; // at ofs: 0x2DE // NOTE: NO LONGER 4 byte aligned!!! @@ -1525,85 +1531,204 @@ typedef struct mainConfig_s { // at ofs: 0x2FE char longDeviceName[CGF_DEVICE_NAME_SIZE]; - //pins at offs 0x0000033E - // 160 bytes + // pins at offs 0x0000033E (all platforms: fixed, unaffected by pinsState_t variant) + // pinsState_t size is PLATFORM-DEPENDENT: + // D else / default / ESP8266: roles[32]+channels[32]+channels2[32]+channelTypes[64] = 160 bytes (0xA0) + // A W800 / BK7252 / BK7252N / XR872 / BL616: roles[48]+channels[48]+channels2[48]+channelTypes[64] = 208 bytes (0xD0) + // B ESPIDF: roles[50]+channels[50]+channels2[50]+channelTypes[64] = 214 bytes (0xD6) + // C RTL8720D / RTL8721DA / RTL8720E / TXW81X: roles[64]+channels[64]+channels2[64]+channelTypes[64] = 256 bytes (0x100) + // All offsets AFTER this field therefore differ by platform group. + // The offset comments below list ALL platform variants in order D / A / B / C. pinsState_t pins; - // startChannelValues at offs 0x000003DE - // 64 * 2 + // startChannelValues at offset: + // 0x000003DE (D: else/default/ESP8266) + // 0x0000040E (A: W800/BK7252/BK7252N/XR872/BL616) + // 0x00000414 (B: ESPIDF) + // 0x0000043E (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) + // 64 * 2 = 128 bytes short startChannelValues[CHANNEL_MAX]; - // unused_fill at offs 0x0000045E - short unused_fill; // correct alignment - // dgr_sendFlags at offs 0x00000460 + // log2lfs at offset: + // 0x0000045E (D: else/default/ESP8266) + // 0x0000048E (A: W800/BK7252/BK7252N/XR872/BL616) + // 0x00000494 (B: ESPIDF) + // 0x000004BE (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) + // + // usage / meaning: + // 0: disabled - else: number of seconds to log (for logging at startup) + number of repetitions + // use log2lf % 31 for "seconds to log", log2lfs / 31 for the number of startups to folow (reduce by 31 for every start, if < 31, set to 0) + // 0 : don't log + // 1 - 30: log (once) for 1 to 30 seconds, set to 0 afterwards + // 31 / 62 93 ... invalid / don't log + // 32 - 61 : log for (log2lfs - 31) seconds during two starts --> set to (log2lfs - 31) after logging, so one log to follow + // ... + // after logging : log2lfs = (log2lfs >= 31) ? (log2lfs - 31) : 0 + uint8_t log2lfs; + byte unused_fill; // correct alignment + // dgr_sendFlags at offset: + // 0x00000460 (D: else/default/ESP8266) + // 0x00000490 (A: W800/BK7252/BK7252N/XR872/BL616) + // 0x00000496 (B: ESPIDF) + // --> NOT aligned for 4 byte int + // --> will be padded to 0x00000498 !!! + // 0x000004C0 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) int dgr_sendFlags; - // dgr_recvFlags at offs 0x00000464 + // dgr_recvFlags at offset: + // 0x00000464 (D: else/default/ESP8266) + // 0x00000494 (A: W800/BK7252/BK7252N/XR872/BL616) + // 0x0000049C (B: ESPIDF - due to padding before (would be 0x0000049A)) + // 0x000004C4 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) int dgr_recvFlags; - // dgr_name at offs 0x00000468 + // dgr_name at offset: + // 0x00000468 (D: else/default/ESP8266) + // 0x00000498 (A: W800/BK7252/BK7252N/XR872/BL616) + // 0x000004A0 (B: ESPIDF - due to padding before (would be 0x0000049E)) + // 0x000004C8 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) char dgr_name[16]; - // at offs 0x478 + // ntpServer at offset: + // 0x00000478 (D: else/default/ESP8266) + // 0x000004A8 (A: W800/BK7252/BK7252N/XR872/BL616) + // 0x000004B0 (B: ESPIDF - due to padding before (would be 0x000004AE)) + // 0x000004D8 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) char ntpServer[32]; + // cal at offset: + // 0x00000498 (D: else/default/ESP8266) + // 0x000004C8 (A: W800/BK7252/BK7252N/XR872/BL616) + // 0x000004D0 (B: ESPIDF - due to padding before (would be 0x000004CE)) + // 0x000004F8 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) // 8 * 4 = 32 bytes cfgPowerMeasurementCalibration_t cal; - // offs 0x000004B8 + // buttonShortPress at offset: + // 0x000004B8 (D: else/default/ESP8266) + // 0x000004E8 (A: W800/BK7252/BK7252N/XR872/BL616) + // 0x000004F0 (B: ESPIDF - due to padding before (would be 0x000004EE)) + // 0x00000518 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) // short press 1 means 100 ms short press time // So basically unit is 0.1 second byte buttonShortPress; - // offs 0x000004B9 + // buttonLongPress at offset: + // 0x000004B9 (D: else/default/ESP8266) + // 0x000004E9 (A: W800/BK7252/BK7252N/XR872/BL616) + // 0x000004F1 (B: ESPIDF - due to padding before (would be 0x000004EF)) + // 0x00000519 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) byte buttonLongPress; - // offs 0x000004BA + // buttonHoldRepeat at offset: + // 0x000004BA (D: else/default/ESP8266) + // 0x000004EA (A: W800/BK7252/BK7252N/XR872/BL616) + // 0x000004F2 (B: ESPIDF - due to padding before (would be 0x000004F0)) + // 0x0000051A (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) byte buttonHoldRepeat; - // offs 0x000004BB + // unused_fill1 at offset: + // 0x000004BB (D: else/default/ESP8266) + // 0x000004EB (A: W800/BK7252/BK7252N/XR872/BL616) + // 0x000004F3 (B: ESPIDF - due to padding before (would be 0x000004F1)) + // 0x000004F1 (B: ESPIDF) + // 0x0000051B (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) byte unused_fill1; - // offset 0x000004BC - unsigned long LFS_Size; // szie of LFS volume. it's aligned against the end of OTA + // LFS_Size at offset: + // 0x000004BC (D: else/default/ESP8266) + // 0x000004EC (A: W800/BK7252/BK7252N/XR872/BL616) + // 0x000004F4 (B: ESPIDF - due to padding before (would be 0x000004F2)) + // 0x0000051C (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) + // NOTE: 'unsigned long' is 4 bytes on all supported 32-bit embedded platforms, + // so no alignment padding is inserted by the compiler here. + // Caution: On 64 bit platforms (like simulator) compiler will use + // alignment to reach 0x4C0 ('unsigned long' is 8 bytes (LP64/64-bit)) + // so the following is only valid for 32 bit targets! + unsigned long LFS_Size; // size of LFS volume, aligned against the end of OTA + // loggerFlags at offset: + // 0x000004C0 (D: else/default/ESP8266) + // 0x000004F0 (A: W800/BK7252/BK7252N/XR872/BL616) + // 0x000004F8 (B: ESPIDF - due to padding before (would be 0x000004F6)) + // 0x00000520 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) int loggerFlags; +// unusedSectorAB: sized per platform to keep obkStaticIP_t, ledRemap_t, led_corr_t +// and the fields following them aligned "identically". +// Sadly this (by incident, I suppose) doesn't align all eqal, but builds two groups: +// groups D and A, +// groups B and C; they (would) "land" 2 bytes earlier (staticIP at 0x0525 instead of 0x0527). +// group B (ESPDIF): due to unaligned "int" before, we also "land" staticIP at 0x0527. +// +// The original "0x0554" comment below (for mqtt_group) is correct for D/A only! #if PLATFORM_W800 || PLATFORM_BK7252 || PLATFORM_BK7252N || PLATFORM_XR872 || PLATFORM_BL616 + // unusedSectorAB: 51 bytes [group A] byte unusedSectorAB[51]; #elif PLATFORM_ESPIDF + // unusedSectorAB: 43 bytes [group B] byte unusedSectorAB[43]; #elif PLATFORM_RTL8720D || PLATFORM_RTL8721DA || PLATFORM_RTL8720E || PLATFORM_TXW81X + // unusedSectorAB: 1 byte [group C] byte unusedSectorAB; -#else +#else + // unusedSectorAB: 99 bytes [group D, default/ESP8266] byte unusedSectorAB[99]; -#endif +#endif + // staticIP at offset: + // 0x00000527 (D: else/default/ESP8266) + // 0x00000527 (A: W800/BK7252/BK7252N/XR872/BL616) + // 0x00000527 (B: ESPIDF - due to padding before (would be 0x00000525)) + // 0x00000525 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) obkStaticIP_t staticIP; + // ledRemap_t (5 bytes): staticIP_off + 16 ledRemap_t ledRemap; + // led_corr_t (24 bytes): ledRemap_off + 5 led_corr_t led_corr; + // mqtt_group at offset: + // 0x00000554 (D: else/default/ESP8266) + // 0x00000554 (A: W800/BK7252/BK7252N/XR872/BL616) + // 0x00000554 (B: ESPIDF - due to padding before (would be 0x00000552)) + // 0x00000552 (C: RTL8720D family) <-- 2 bytes earlier than D/A // alternate topic name for receiving MQTT commands - // offset 0x00000554 char mqtt_group[64]; - // offs 0x00000594 + // offs 0x00000594 (D: else/default/ESP8266 and A: W800/BK7252/BK7252N/XR872/BL616 - and (due to padding) B: ESPIDF) + // offs 0x00000592 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) byte unused_bytefill[3]; - // offs 0x00000597 + // offs 0x00000597 (D: else/default/ESP8266 and A: W800/BK7252/BK7252N/XR872/BL616 - and (due to padding) B: ESPIDF) + // offs 0x00000595 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) byte timeRequiredToMarkBootSuccessfull; - //offs 0x00000598 + // offs 0x00000598 (D: else/default/ESP8266 and A: W800/BK7252/BK7252N/XR872/BL616 - and (due to padding) B: ESPIDF) + // offs 0x00000596 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) int ping_interval; int ping_seconds; - // 0x000005A0 + // ping_host at offs 0x000005A0 (D: else/default/ESP8266 and A: W800/BK7252/BK7252N/XR872/BL616 - and (due to padding) B: ESPIDF) + // offs 0x0000059E (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) char ping_host[64]; - // ofs 0x000005E0 (dec 1504) + // initCommandLine at offs 0x000005E0 (D: else/default/ESP8266 and A: W800/BK7252/BK7252N/XR872/BL616 - and (due to padding) B: ESPIDF) + // offs 0x000005DE (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) (dec 1504 for D/A) //char initCommandLine[512]; #define ALLOW_SSID2 1 #define ALLOW_WEB_PASSWORD 1 char initCommandLine[1568]; - // offset 0x00000C00 (3072 decimal) + // wifi_ssid2 at offs 0x00000C00 (D: else/default/ESP8266 and A: W800/BK7252/BK7252N/XR872/BL616 - and (due to padding) B: ESPIDF) + // offs 0x00000BFE (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) char wifi_ssid2[64]; - // offset 0x00000C40 (3136 decimal) + // wifi_pass2 at offs 0x00000C40 (D: else/default/ESP8266 and A: W800/BK7252/BK7252N/XR872/BL616 - and (due to padding) B: ESPIDF) + // offs 0x00000C3E (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) char wifi_pass2[68]; - // offset 0x00000C84 (3204 decimal) + // webPassword at offs 0x00000C84 (D: else/default/ESP8266 and A: W800/BK7252/BK7252N/XR872/BL616 - and (due to padding) B: ESPIDF) + // offs 0x00000C82 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) char webPassword[33]; - // offset 0x00000CA5 (3237 decimal) + // mqtt_use_tls at offs 0x00000CA5 (D: else/default/ESP8266 and A: W800/BK7252/BK7252N/XR872/BL616 - and (due to padding) B: ESPIDF) + // offs 0x00000CA3 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) byte mqtt_use_tls; - // offset 0x00000CA6 (3238 decimal) + // mqtt_verify_tls_cert at offs 0x00000CA6 (D: else/default/ESP8266 and A: W800/BK7252/BK7252N/XR872/BL616 - and (due to padding) B: ESPIDF) + // offs 0x00000CA4 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) byte mqtt_verify_tls_cert; - // offset 0x00000CA7 (3239 decimal) + // mqtt_cert_file at offs 0x00000CA7 (D: else/default/ESP8266 and A: W800/BK7252/BK7252N/XR872/BL616 - and (due to padding) B: ESPIDF) + // offs 0x00000CA5 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) char mqtt_cert_file[20]; - // offset 0x00000CBB (3259 decimal) + // disable_web_server at offs 0x00000CBB (D: else/default/ESP8266 and A: W800/BK7252/BK7252N/XR872/BL616 - and (due to padding) B: ESPIDF) + // offs 0x00000CB9 (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) byte disable_web_server; - // offset 0x00000CBC (3260 decimal) + // unused[324] at offs 0x00000CBC (D: else/default/ESP8266 and A: W800/BK7252/BK7252N/XR872/BL616 - and (due to padding) B: ESPIDF) + // offs 0x00000CBA (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) + // + // total struct size: 0x0E00 (= 3584 bytes) (D: else/default/ESP8266 and A: W800/BK7252/BK7252N/XR872/BL616 - and (due to padding) B: ESPIDF) + // total struct size: 0x0DFE (= 3582 bytes) (C: RTL8720D/RTL8721DA/RTL8720E/TXW81X) char unused[324]; } mainConfig_t; + // one sector is 4096 so it we still have some expand possibility #define MAGIC_CONFIG_SIZE_V3 2016 #define MAGIC_CONFIG_SIZE_V4 3584 diff --git a/src/obk_config.h b/src/obk_config.h index 95304b56b..e2cd647a0 100644 --- a/src/obk_config.h +++ b/src/obk_config.h @@ -744,5 +744,11 @@ #undef ENABLE_DRIVER_IR #endif +// test for writing log to LFS: enable for all platforms, if FLS is present: +#if ENABLE_LITTLEFS +#define ENABLE_LOG2LFS 1 +#endif +#define ENABLE_CHECK_CFG 1 + // closing OBK_CONFIG_H #endif diff --git a/src/user_main.c b/src/user_main.c index a7dec2678..4090232d4 100644 --- a/src/user_main.c +++ b/src/user_main.c @@ -35,6 +35,7 @@ #if ENABLE_LITTLEFS #include "littlefs/our_lfs.h" +uint8_t g_log2lfs; #endif @@ -1476,6 +1477,175 @@ void Main_ForceUnsafeInit() { Main_Init_AfterDelay_Unsafe(false); bSafeMode = 0; } + + +// inspired by test in win_main.c with a small extension to +// simplify testing with a function +// removed from win_main.c, so enabled for WINDOWS +#if ENABLE_CHECK_CFG || WINDOWS +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + +struct OffsetCheck { + const char *fieldName; + size_t expected; + size_t actual; +}; + +#define CHECK(FIELD, EXPECTED) { #FIELD, EXPECTED, OFFSETOF(mainConfig_t, FIELD) } + +void validateMainConfigOffsets(void) { + const struct OffsetCheck checks[] = { + // Starting with bese offsets (same for all platforms + CHECK(ident0, 0x00000000), + CHECK(version, 0x00000004), + CHECK(genericFlags, 0x00000008), + CHECK(genericFlags2, 0x0000000C), + CHECK(changeCounter, 0x00000010), + CHECK(wifi_ssid, 0x00000014), + CHECK(wifi_pass, 0x00000054), + CHECK(mqtt_host, 0x00000094), + CHECK(mqtt_clientId, 0x00000194), + CHECK(mqtt_userName, 0x000001D4), + CHECK(mqtt_pass, 0x00000214), + CHECK(mqtt_port, 0x00000294), + CHECK(webappRoot, 0x00000298), + CHECK(mac, 0x000002D8), + CHECK(shortDeviceName, 0x000002DE), + CHECK(longDeviceName, 0x000002FE), + CHECK(pins, 0x0000033E), + +#if PLATFORM_W800 || PLATFORM_BK7252 || PLATFORM_BK7252N || PLATFORM_XR872 || PLATFORM_BL616 + // PLATFORM GROUP A + CHECK(startChannelValues, 0x0000040E), + CHECK(log2lfs, 0x0000048E), + CHECK(unused_fill, 0x0000048F), + CHECK(dgr_sendFlags, 0x00000490), + CHECK(dgr_recvFlags, 0x00000494), + CHECK(dgr_name, 0x00000498), + CHECK(ntpServer, 0x000004A8), + CHECK(cal, 0x000004C8), + CHECK(buttonShortPress, 0x000004E8), + CHECK(buttonLongPress, 0x000004E9), + CHECK(LFS_Size, 0x000004EC), + CHECK(loggerFlags, 0x000004F0), + CHECK(mqtt_group, 0x00000554), + CHECK(webPassword, 0x00000C84), + CHECK(mqtt_use_tls, 0x00000CA5), + CHECK(mqtt_verify_tls_cert, 0x00000CA6), + CHECK(mqtt_cert_file, 0x00000CA7), + CHECK(disable_web_server, 0x00000CBB), + CHECK(unused, 0x00000CBC), + +#elif PLATFORM_ESPIDF + // PLATFORM GROUP B + CHECK(startChannelValues, 0x00000414), + CHECK(log2lfs, 0x00000494), + CHECK(unused_fill, 0x00000495), +// missing padding in struct for next "int" dgr_sendFlags +// would be 0x00000496 else but needs 4 byte alignment + CHECK(dgr_sendFlags, 0x00000498), + CHECK(dgr_recvFlags, 0x0000049C), + CHECK(dgr_name, 0x000004A0), + CHECK(ntpServer, 0x000004B0), + CHECK(cal, 0x000004D0), + CHECK(buttonShortPress, 0x000004F0), + CHECK(buttonLongPress, 0x000004F1), + CHECK(LFS_Size, 0x000004F4), + CHECK(loggerFlags, 0x000004F8), + CHECK(mqtt_group, 0x00000554), + CHECK(webPassword, 0x00000C84), + CHECK(mqtt_use_tls, 0x00000CA5), + CHECK(mqtt_verify_tls_cert, 0x00000CA6), + CHECK(mqtt_cert_file, 0x00000CA7), + CHECK(disable_web_server, 0x00000CBB), + CHECK(unused, 0x00000CBC), + +#elif PLATFORM_RTL8720D || PLATFORM_RTL8721DA || PLATFORM_RTL8720E || PLATFORM_TXW81X + // PLATFORM GROUP C + CHECK(startChannelValues, 0x0000043E), + CHECK(log2lfs, 0x000004BE), + CHECK(unused_fill, 0x000004BF), + CHECK(dgr_sendFlags, 0x000004C0), + CHECK(dgr_recvFlags, 0x000004C4), + CHECK(dgr_name, 0x000004C8), + CHECK(ntpServer, 0x000004D8), + CHECK(cal, 0x000004F8), + CHECK(buttonShortPress, 0x00000518), + CHECK(buttonLongPress, 0x00000519), + CHECK(LFS_Size, 0x0000051C), + CHECK(loggerFlags, 0x00000520), + CHECK(mqtt_group, 0x00000552), + CHECK(webPassword, 0x00000C82), + CHECK(mqtt_use_tls, 0x00000CA3), + CHECK(mqtt_verify_tls_cert, 0x00000CA4), + CHECK(mqtt_cert_file, 0x00000CA5), + CHECK(disable_web_server, 0x00000CB9), + CHECK(unused, 0x00000CBA), + +#else + // PLATFORM GROUP D (Default/ESP8266) + CHECK(startChannelValues, 0x000003DE), + CHECK(log2lfs, 0x0000045E), + CHECK(unused_fill, 0x0000045F), + CHECK(dgr_sendFlags, 0x00000460), + CHECK(dgr_recvFlags, 0x00000464), + CHECK(dgr_name, 0x00000468), + CHECK(ntpServer, 0x00000478), + CHECK(cal, 0x00000498), + CHECK(buttonShortPress, 0x000004B8), + CHECK(buttonLongPress, 0x000004B9), + CHECK(buttonHoldRepeat, 0x000004BA), + CHECK(unused_fill1, 0x000004BB), + CHECK(LFS_Size, 0x000004BC), + CHECK(loggerFlags, 0x000004C0), + CHECK(mqtt_group, 0x00000554), + CHECK(webPassword, 0x00000C84), + CHECK(mqtt_use_tls, 0x00000CA5), + CHECK(mqtt_verify_tls_cert, 0x00000CA6), + CHECK(mqtt_cert_file, 0x00000CA7), + CHECK(disable_web_server, 0x00000CBB), + CHECK(unused, 0x00000CBC), +#endif + }; + + + int errorCount = 0; + + // Check individual field offsets + for (size_t i = 0; i < sizeof(checks) / sizeof(checks[0]); i++) { + if (checks[i].actual != checks[i].expected) { + bk_printf("ERROR: OFFSETOF(mainConfig_t, %s)\n" + " Expected: 0x%08lX\n" + " Actual: 0x%08lX\n", + checks[i].fieldName, (unsigned long)checks[i].expected, (unsigned long)checks[i].actual); + errorCount++; + } + } + + // Check struct size + #define EXPECTED_STRUCT_SIZE 0x00000E00 // 3584 bytes + size_t actualSize = sizeof(mainConfig_t); + + if (actualSize != EXPECTED_STRUCT_SIZE) { + bk_printf("ERROR: sizeof(mainConfig_t)\n" + " Expected: 0x%08lX (%lu bytes)\n" + " Actual: 0x%08lX (%lu bytes)\n", + (unsigned long)EXPECTED_STRUCT_SIZE, (unsigned long)EXPECTED_STRUCT_SIZE, + (unsigned long)actualSize, (unsigned long)actualSize); + errorCount++; + } + + if (errorCount > 0) { + bk_printf("\n%d offset validation(s) failed!\n", errorCount); + } else { + bk_printf("All mainConfig_t offsets validated successfully!\n"); + } +} + +#endif // ENABLE_CHECK_CFG && || WINDOWS + + + ////////////////////////////////////////////////////// // do things which should happen BEFORE we delay at Startup // e.g. set lights to last value, so we get immediate response at @@ -1507,7 +1677,9 @@ void Main_Init_Before_Delay() #if ENABLE_LITTLEFS LFSAddCmds(); #endif - +#if ENABLE_CHECK_CFG || WINDOWS + validateMainConfigOffsets(); +#endif // only initialise certain things if we are not in AP mode if (!bSafeMode) { @@ -1618,6 +1790,26 @@ void Main_Init_After_Delay() } #endif Main_Init_AfterDelay_Unsafe(true); +#if ENABLE_LITTLEFS && ENABLE_LOG2LFS + // we have to wait until berry was run - it will else somewhow reinit/remount lfs and + // log2lfs will crash when its already writing ... + // defines/macros (LOG2LFS_SECONDS) included from logging.h + void initLog2LFS(void); // implemented in logging.c + // Now CFG flash is ininitialized, immediatley check + // if we want startup log to be saved to LFS + g_log2lfs = LOG2LFS_SECONDS(CFG_Get_log2lfs()); +#if WINDOWS + // don't run log2lfs in selTestMode - it will kill LFS while + // log2lfs uses LFS + extern int g_selfTestsMode; + if ( g_selfTestsMode != 0) g_log2lfs = 0; + // for testing: set to log first 20 seconds + else + if (g_log2lfs == 0) g_log2lfs = 20; +#endif + if (g_log2lfs > 0) initLog2LFS(); +// bk_printf("g_log2lfs=%i\r\n", g_log2lfs); +#endif } ADDLOGF_INFO("%s done", __func__); diff --git a/src/win_main.c b/src/win_main.c index efa1683ba..5847b5e2e 100644 --- a/src/win_main.c +++ b/src/win_main.c @@ -42,8 +42,6 @@ #include "selftest/selftest_local.h" #include "new_pins.h" -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - // Need to link with Ws2_32.lib #pragma comment(lib, "Ws2_32.lib") // #pragma comment (lib, "Mswsock.lib") @@ -490,12 +488,14 @@ int __cdecl main(int argc, char **argv) printf("sizeof(float) = %d\n", (int)sizeof(float)); printf("sizeof(double) = %d\n", (int)sizeof(double)); printf("sizeof(long double) = %d\n", (int)sizeof(long double)); + printf("sizeof(time_t) = %d\n", (int)sizeof(time_t)); + printf("sizeof(ENERGY_METERING_DATA) = %d\n", (int)sizeof(ENERGY_METERING_DATA)); printf("sizeof(led_corr_t) = %d\n", (int)sizeof(led_corr_t)); printf("sizeof(mainConfig_t) = %d\n", (int)sizeof(mainConfig_t)); if (sizeof(FLASH_VARS_STRUCTURE) != MAGIC_FLASHVARS_SIZE) { - printf("sizeof(FLASH_VARS_STRUCTURE) != MAGIC_FLASHVARS_SIZE!: %i\n", sizeof(FLASH_VARS_STRUCTURE)); + printf("sizeof(FLASH_VARS_STRUCTURE) != MAGIC_FLASHVARS_SIZE!: %i != %i\n", sizeof(FLASH_VARS_STRUCTURE),MAGIC_FLASHVARS_SIZE); system("pause"); } if (sizeof(ledRemap_t) != MAGIC_LED_REMAP_SIZE) @@ -514,111 +514,135 @@ int __cdecl main(int argc, char **argv) printf("sizeof(mainConfig_t) != MAGIC_CONFIG_SIZE!: %i\n", sizeof(mainConfig_t)); system("pause"); } +// moved to user_main.c + +/* if (OFFSETOF(mainConfig_t, staticIP) != 0x00000527) { - printf("OFFSETOF(mainConfig_t, staticIP) != 0x00000527z: %i\n", OFFSETOF(mainConfig_t, staticIP)); + printf("OFFSETOF(mainConfig_t, staticIP) != 0x00000527: 0x%08X\n", OFFSETOF(mainConfig_t, staticIP)); system("pause"); } if (OFFSETOF(mainConfig_t, wifi_ssid) != 0x00000014) { - printf("OFFSETOF(mainConfig_t, wifi_ssid) != 0x00000014: %i\n", OFFSETOF(mainConfig_t, wifi_ssid)); + printf("OFFSETOF(mainConfig_t, wifi_ssid) != 0x00000014: 0x%08X\n", OFFSETOF(mainConfig_t, wifi_ssid)); system("pause"); } if (OFFSETOF(mainConfig_t, wifi_pass) != 0x00000054) { - printf("OFFSETOF(mainConfig_t, wifi_pass) != 0x00000054: %i\n", OFFSETOF(mainConfig_t, wifi_pass)); + printf("OFFSETOF(mainConfig_t, wifi_pass) != 0x00000054: 0x%08X\n", OFFSETOF(mainConfig_t, wifi_pass)); + system("pause"); + } + if (OFFSETOF(mainConfig_t, log2lfs) != 0x0000045E) + { + printf("OFFSETOF(mainConfig_t, log2lfs) != 0x0000045E: 0x%08X\n", OFFSETOF(mainConfig_t, log2lfs)); + system("pause"); + } + if (OFFSETOF(mainConfig_t, unused_fill) != 0x0000045F) + { + printf("OFFSETOF(mainConfig_t, unused_fill) != 0x0000045F: 0x%08X\n", OFFSETOF(mainConfig_t, unused_fill)); system("pause"); } - if (OFFSETOF(mainConfig_t, unused_fill) != 0x0000045E) + if (OFFSETOF(mainConfig_t, ntpServer) != 0x00000478) { - printf("OFFSETOF(mainConfig_t, unused_fill) != 0x0000045E: %i\n", OFFSETOF(mainConfig_t, unused_fill)); + printf("OFFSETOF(mainConfig_t, ntpServer) != 0x00000478: 0x%08X\n", OFFSETOF(mainConfig_t, ntpServer)); + system("pause"); + } + if (OFFSETOF(mainConfig_t, cal) != 0x00000498) + { + printf("OFFSETOF(mainConfig_t, cal) != 0x00000498: 0x%08X\n", OFFSETOF(mainConfig_t, cal)); system("pause"); } if (OFFSETOF(mainConfig_t, buttonHoldRepeat) != 0x000004BA) { - printf("OFFSETOF(mainConfig_t, buttonHoldRepeat) != 0x000004BA: %i\n", OFFSETOF(mainConfig_t, buttonHoldRepeat)); + printf("OFFSETOF(mainConfig_t, buttonHoldRepeat) != 0x000004BA: 0x%08X\n", OFFSETOF(mainConfig_t, buttonHoldRepeat)); + system("pause"); + } + if (OFFSETOF(mainConfig_t, unused_fill1) != 0x000004BB) + { + printf("OFFSETOF(mainConfig_t, unused_fill1) != 0x000004BB: 0x%08X\n", OFFSETOF(mainConfig_t, unused_fill1)); system("pause"); } if (OFFSETOF(mainConfig_t, shortDeviceName) != 0x2DE) { - printf("OFFSETOF(mainConfig_t, shortDeviceName) != 0x2DE: %i\n", OFFSETOF(mainConfig_t, shortDeviceName)); + printf("OFFSETOF(mainConfig_t, shortDeviceName) != 0x2DE: 0x%08X\n", OFFSETOF(mainConfig_t, shortDeviceName)); system("pause"); } if (OFFSETOF(mainConfig_t, timeRequiredToMarkBootSuccessfull) != 0x00000597) { - printf("OFFSETOF(mainConfig_t, timeRequiredToMarkBootSuccessfull) != 0x00000597: %i\n", OFFSETOF(mainConfig_t, timeRequiredToMarkBootSuccessfull)); + printf("OFFSETOF(mainConfig_t, timeRequiredToMarkBootSuccessfull) != 0x00000597: 0x%08X\n", OFFSETOF(mainConfig_t, timeRequiredToMarkBootSuccessfull)); system("pause"); } if (OFFSETOF(mainConfig_t, dgr_sendFlags) != 0x00000460) { - printf("OFFSETOF(mainConfig_t, dgr_sendFlags) != 0x00000460: %i\n", OFFSETOF(mainConfig_t, dgr_sendFlags)); + printf("OFFSETOF(mainConfig_t, dgr_sendFlags) != 0x00000460: 0x%08X\n", OFFSETOF(mainConfig_t, dgr_sendFlags)); system("pause"); } if (OFFSETOF(mainConfig_t, mqtt_host) != 0x00000094) { - printf("OFFSETOF(mainConfig_t, mqtt_host) != 0x00000094: %i\n", OFFSETOF(mainConfig_t, mqtt_host)); + printf("OFFSETOF(mainConfig_t, mqtt_host) != 0x00000094: 0x%08X\n", OFFSETOF(mainConfig_t, mqtt_host)); system("pause"); } if (OFFSETOF(mainConfig_t, mqtt_userName) != 0x1D4) { - printf("OFFSETOF(mainConfig_t, mqtt_userName) != 0x1D4: %i\n", OFFSETOF(mainConfig_t, mqtt_userName)); + printf("OFFSETOF(mainConfig_t, mqtt_userName) != 0x1D4: 0x%03X\n", OFFSETOF(mainConfig_t, mqtt_userName)); system("pause"); } if (OFFSETOF(mainConfig_t, mqtt_port) != 0x294) { - printf("OFFSETOF(mainConfig_t, mqtt_port) != 0x294: %i\n", OFFSETOF(mainConfig_t, mqtt_port)); + printf("OFFSETOF(mainConfig_t, mqtt_port) != 0x294: 0x%03X\n", OFFSETOF(mainConfig_t, mqtt_port)); system("pause"); } if (OFFSETOF(mainConfig_t, mqtt_group) != 0x00000554) { - printf("OFFSETOF(mainConfig_t, mqtt_group) != 0x00000554: %i\n", OFFSETOF(mainConfig_t, mqtt_group)); + printf("OFFSETOF(mainConfig_t, mqtt_group) != 0x00000554: 0x%08X\n", OFFSETOF(mainConfig_t, mqtt_group)); system("pause"); } if (OFFSETOF(mainConfig_t, LFS_Size) != 0x000004BC) { - printf("OFFSETOF(mainConfig_t, LFS_Size) != 0x000004BC: %i\n", OFFSETOF(mainConfig_t, LFS_Size)); + printf("OFFSETOF(mainConfig_t, LFS_Size) != 0x000004BC: 0x%08X\n", OFFSETOF(mainConfig_t, LFS_Size)); system("pause"); } if (OFFSETOF(mainConfig_t, ping_host) != 0x000005A0) { - printf("OFFSETOF(mainConfig_t, ping_host) != 0x000005A0: %i\n", OFFSETOF(mainConfig_t, ping_host)); + printf("OFFSETOF(mainConfig_t, ping_host) != 0x000005A0: 0x%08X\n", OFFSETOF(mainConfig_t, ping_host)); system("pause"); } if (OFFSETOF(mainConfig_t, buttonShortPress) != 0x000004B8) { - printf("OFFSETOF(mainConfig_t, buttonShortPress) != 0x000004B8: %i\n", OFFSETOF(mainConfig_t, buttonShortPress)); + printf("OFFSETOF(mainConfig_t, buttonShortPress) != 0x000004B8: 0x%08X\n", OFFSETOF(mainConfig_t, buttonShortPress)); system("pause"); } if (OFFSETOF(mainConfig_t, pins) != 0x0000033E) { - printf("OFFSETOF(mainConfig_t, pins) != 0x0000033E: %i\n", OFFSETOF(mainConfig_t, pins)); + printf("OFFSETOF(mainConfig_t, pins) != 0x0000033E: 0x%08X\n", OFFSETOF(mainConfig_t, pins)); system("pause"); } if (OFFSETOF(mainConfig_t, version) != 0x00000004) { - printf("OFFSETOF(mainConfig_t, version) != 0x00000004: %i\n", OFFSETOF(mainConfig_t, version)); + printf("OFFSETOF(mainConfig_t, version) != 0x00000004: 0x%08X\n", OFFSETOF(mainConfig_t, version)); system("pause"); } if (OFFSETOF(mainConfig_t, initCommandLine) != 0x000005E0) { - printf("OFFSETOF(mainConfig_t, initCommandLine) != 0x000005E0: %i\n", OFFSETOF(mainConfig_t, initCommandLine)); + printf("OFFSETOF(mainConfig_t, initCommandLine) != 0x000005E0: 0x%08X\n", OFFSETOF(mainConfig_t, initCommandLine)); system("pause"); } if (OFFSETOF(mainConfig_t, wifi_ssid2) != 0x00000C00) { - printf("OFFSETOF(mainConfig_t, wifi_ssid2) != 0x00000C00: %i\n", OFFSETOF(mainConfig_t, wifi_ssid2)); + printf("OFFSETOF(mainConfig_t, wifi_ssid2) != 0x00000C00: 0x%08X\n", OFFSETOF(mainConfig_t, wifi_ssid2)); system("pause"); } if (OFFSETOF(mainConfig_t, wifi_pass2) != 0x00000C40) { - printf("OFFSETOF(mainConfig_t, wifi_pass2) != 0x00000C40: %i\n", OFFSETOF(mainConfig_t, wifi_pass2)); + printf("OFFSETOF(mainConfig_t, wifi_pass2) != 0x00000C40: 0x%08X\n", OFFSETOF(mainConfig_t, wifi_pass2)); system("pause"); } if (OFFSETOF(mainConfig_t, unused) != 0x00000CA5) { - // printf("OFFSETOF(mainConfig_t, unused) != 0x00000CA5: %i\n", OFFSETOF(mainConfig_t, unused)); + // printf("OFFSETOF(mainConfig_t, unused) != 0x00000CA5: 0x%08X\n", OFFSETOF(mainConfig_t, unused)); // system("pause"); } +*/ // Test expansion // CMD_UART_Send_Hex(0,0,"FFAA$CH1$BB",0);