# HG changeset patch # User heinrichsweikamp # Date 1582010429 0 # Node ID 30580cf5ee77c013267733356a47b6c4d170f26a # Parent c2264ce139cb603de9887b13caa9377a5d82b7ed# Parent 7f351c25608adba92eeaef8c874f91bd63e68910 Merged in Ideenmodellierer/ostc4/ImprovmentNVM_2 (pull request #39) ImprovmentNVM 2 diff -r c2264ce139cb -r 30580cf5ee77 Discovery/Inc/externLogbookFlash.h --- a/Discovery/Inc/externLogbookFlash.h Mon Feb 10 08:23:15 2020 +0000 +++ b/Discovery/Inc/externLogbookFlash.h Tue Feb 18 07:20:29 2020 +0000 @@ -59,18 +59,18 @@ */ #define SETTINGSSTART 0x00010000 #define SETTINGSSTOP 0x0001FFFF -#define VPMSTART 0x00020000 -#define VPMSTOP 0x0002FFFF +#define VPMSTART 0x00020000 +#define VPMSTOP 0x0002FFFF #define unused3START 0x00030000 #define unused3STOP 0x0007FFFF #define HEADERSTART 0x00080000 #define HEADERSTOP 0x000FFFFF #define SAMPLESTART 0x00100000 #define SAMPLESTOP 0x00CFFFFF -#define FWSTART 0x00D00000 -#define FWSTOP 0x00DFFFFF -#define FWSTART2 0x00E00000 -#define FWSTOP2 0x00FFFFFF +#define FWSTART 0x00D00000 +#define FWSTOP 0x00DFFFFF +#define FWSTART2 0x00E00000 +#define FWSTOP2 0x00FFFFFF /* 16 MB with 4 Byte addressing */ #define unused4START 0x01000000 #define unused4STOP 0x01FFFFFF @@ -78,6 +78,12 @@ #define HEADERSIZE sizeof(SLogbookHeader) #define HEADERSIZEOSTC3 sizeof(SLogbookHeaderOSTC3) +/* Sample ring buffer sector states derived from the usage at begin and end of a sector */ +#define SECTOR_CLOSED (0) +#define SECTOR_NOTUSED (1) +#define SECTOR_INUSE (4) +#define SECTOR_EMPTY (5) + /* Exported types ------------------------------------------------------------*/ typedef struct{ uint8_t byteLow; @@ -102,10 +108,10 @@ } convert16_Type; /* Exported functions --------------------------------------------------------*/ -void ext_flash_write_settings(void); +void ext_flash_write_settings(uint8_t resetRing); uint8_t ext_flash_read_settings(void); -void ext_flash_write_devicedata(void); +void ext_flash_write_devicedata(uint8_t resetRing); uint16_t ext_flash_read_devicedata(uint8_t *buffer, uint16_t max_length); void ext_flash_read_fixed_16_devicedata_blocks_formated_128byte_total(uint8_t *buffer); @@ -157,4 +163,7 @@ uint16_t ext_flash_repair_SPECIAL_dive_numbers_starting_count_with(uint16_t startCount); +uint32_t ext_flash_AnalyseSampleBuffer(char *pstrResult); +void ext_flash_CloseSector(void); + #endif /* EXTERN_LOGBOOK_FLASH_H */ diff -r c2264ce139cb -r 30580cf5ee77 Discovery/Inc/tStructure.h --- a/Discovery/Inc/tStructure.h Mon Feb 10 08:23:15 2020 +0000 +++ b/Discovery/Inc/tStructure.h Tue Feb 18 07:20:29 2020 +0000 @@ -290,19 +290,19 @@ #define StMSYS5_Info _MB(2,8,5,1,0) -#define StMSYS6_Exit _MB(2,8,6,1,0) +#define StMSYS6_Exit _MB(2,8,6,1,0) #define StMSYS6_LogbookOffset _MB(2,8,6,7,0) -#define StMSYS6_ResetAll _MB(2,8,6,2,0) -#define StMSYS6_ResetDeco _MB(2,8,6,3,0) -#define StMSYS6_Reboot _MB(2,8,6,4,0) +#define StMSYS6_ResetAll _MB(2,8,6,2,0) +#define StMSYS6_ResetDeco _MB(2,8,6,3,0) +#define StMSYS6_Reboot _MB(2,8,6,4,0) #define StMSYS6_Maintenance _MB(2,8,6,5,0) #define StMSYS6_ResetLogbook _MB(2,8,6,6,0) #define StMSYS6_SetBattCharge _MB(2,8,6,7,0) -#define StMSYS6_RebootRTE _MB(2,8,6,8,0) +#define StMSYS6_RebootRTE _MB(2,8,6,8,0) #define StMSYS6_RebootMainCPU _MB(2,8,6,9,0) #define StMSYS6_ScreenTest _MB(2,8,6,10,0) #define StMSYS6_SetFactoryBC _MB(2,8,6,11,0) - +#define StMSYS6_SetSampleIndx _MB(2,8,6,12,0) /* PAGE 9 */ #define StMPLAN _MB(2,9,0,0,0) diff -r c2264ce139cb -r 30580cf5ee77 Discovery/Inc/text_multilanguage.h --- a/Discovery/Inc/text_multilanguage.h Mon Feb 10 08:23:15 2020 +0000 +++ b/Discovery/Inc/text_multilanguage.h Tue Feb 18 07:20:29 2020 +0000 @@ -288,6 +288,7 @@ TXT2BYTE_Maintenance, TXT2BYTE_SetBatteryCharge, TXT2BYTE_SetFactoryDefaults, + TXT2BYTE_SetSampleIndex, TXT2BYTE_Reboot, TXT2BYTE_ButtonLeft, TXT2BYTE_ButtonMitte, diff -r c2264ce139cb -r 30580cf5ee77 Discovery/Src/base.c --- a/Discovery/Src/base.c Mon Feb 10 08:23:15 2020 +0000 +++ b/Discovery/Src/base.c Tue Feb 18 07:20:29 2020 +0000 @@ -230,6 +230,7 @@ #include "test_vpm.h" #include "tDebug.h" #include "motion.h" +#include "data_exchange_main.h" #ifdef DEMOMODE #include "demo.h" @@ -262,6 +263,8 @@ TIM_HandleTypeDef TimDemoHandle; /* used in stm32f4xx_it.c too */ #endif +static uint8_t RequestModeChange = 0; + static uint8_t LastButtonPressed; static uint32_t LastButtonPressedTick; static uint32_t BaseTick100ms; /* Tick at last 100ms cycle */ @@ -300,6 +303,8 @@ static void TriggerButtonAction(void); static void EvaluateButton(void); static void RefreshDisplay(void); +static void TimeoutControlRequestModechange(void); +static void TimeoutControl(void); /* ITM Trace-------- ---------------------------------------------------------*/ /* @@ -450,7 +455,7 @@ if( settingsGetPointer()->debugModeOnStart ) { settingsGetPointer()->debugModeOnStart = 0; - ext_flash_write_settings(); + ext_flash_write_settings(0); setDebugMode(); openInfo( StIDEBUG ); } @@ -476,14 +481,14 @@ { createDiveSettings(); updateMenu(); - ext_flash_write_settings(); + ext_flash_write_settings(0); } /* check if tasks depending on global state are pending */ get_globalStateList(&status); if(status.base == BaseHome) { - tMenuEdit_writeSettingsToFlash(); // takes 900 ms!! + tMenuEdit_writeSettingsToFlash(); } DataEX_merge_devicedata(); /* data is exchanged at startup and every 10 minutes => check if something changed */ @@ -495,6 +500,8 @@ DoDisplayRefresh = 0; RefreshDisplay(); + TimeoutControl(); /* exit menus if needed */ + if(stateUsed->mode == MODE_DIVE) /* handle motion events in divemode only */ { switch(settingsGetPointer()->MotionDetection) @@ -583,23 +590,11 @@ return; } #endif - static uint8_t last_base; - SStateList status; - uint32_t timeout_in_seconds; - uint32_t timeout_limit_Surface_in_seconds; - + _Bool modeChange = 0; BaseTick100ms = HAL_GetTick(); /* store start of 100ms cycle */ - _Bool InDiveMode = 0; - _Bool modeChange = 0; // to exit from menu and logbook - - if(stateUsed->mode == MODE_DIVE) - InDiveMode = 1; - else - InDiveMode = 0; - EvaluateButton(); if(returnFromCommCleanUpRequest) @@ -652,132 +647,11 @@ break; } - /* timeout control */ - if(modeChange) ///< from RTE, set in data_exchange_main.c - time_without_button_pressed_deciseconds = (settingsGetPointer()->timeoutSurfacemode / 4) * 3; - if(status.base != last_base) - time_without_button_pressed_deciseconds = 0; - last_base = status.base; - timeout_in_seconds = time_without_button_pressed_deciseconds / 10; - time_without_button_pressed_deciseconds += 1; - if(modeChange || (timeout_in_seconds != time_without_button_pressed_deciseconds / 10)) + get_globalStateList(&status); + if(modeChange) { -#ifdef NO_TIMEOUT - timeout_in_seconds = 0; -#else - timeout_in_seconds += 1; -#endif - - if(InDiveMode) - { - switch(status.base) - { - case BaseHome: - if((status.line != 0) && (timeout_in_seconds >= settingsGetPointer()->timeoutEnterButtonSelectDive)) - { - set_globalState(StD); - timeout_in_seconds = 0; - } - break; - - case BaseMenu: - if((status.line == 0) && ((timeout_in_seconds >= settingsGetPointer()->timeoutMenuDive) || modeChange)) - { - exitMenu(); - timeout_in_seconds = 0; - } - if((status.line != 0) && ((timeout_in_seconds >= settingsGetPointer()->timeoutMenuEdit) || modeChange)) - { - exitMenuEdit_to_Home(); - timeout_in_seconds = 0; - } - break; - default: - break; - } - } - else /* surface mode */ - { - switch(status.base) - { - case BaseHome: - // added hw 161027 - if(!(stateRealGetPointer()->warnings.lowBattery) && (stateRealGetPointer()->lifeData.battery_charge > 9)) - { - stateRealGetPointerWrite()->lastKnownBatteryPercentage = stateRealGetPointer()->lifeData.battery_charge; - } - else if((wasFirmwareUpdateCheckBattery) && (timeout_in_seconds > 3)) - { - wasFirmwareUpdateCheckBattery = 0; - setButtonResponsiveness(settingsGetPointer()->ButtonResponsiveness); // added 170306 - if( (settingsGetPointer()->lastKnownBatteryPercentage > 0) - && (settingsGetPointer()->lastKnownBatteryPercentage <= 100) - && (stateRealGetPointer()->warnings.lowBattery)) - { - setBatteryPercentage(settingsGetPointer()->lastKnownBatteryPercentage); - } - } - // stuff before and new @161121 CCR-sensor limit 10 minutes - if((settingsGetPointer()->dive_mode == DIVEMODE_CCR) && (settingsGetPointer()->CCR_Mode == CCRMODE_Sensors)) - { - timeout_limit_Surface_in_seconds = settingsGetPointer()->timeoutSurfacemodeWithSensors; - } - else - { - timeout_limit_Surface_in_seconds = settingsGetPointer()->timeoutSurfacemode; - } - if(timeout_in_seconds >= timeout_limit_Surface_in_seconds) - { - gotoSleep(); - } - break; - case BaseMenu: - if((status.line == 0) && ((timeout_in_seconds >= settingsGetPointer()->timeoutMenuSurface) || modeChange)) - { - exitMenu(); - timeout_in_seconds = 0; - } - if((status.line != 0) && ((timeout_in_seconds >= settingsGetPointer()->timeoutMenuEdit) || modeChange)) - { - if((status.page != (uint8_t)((StMPLAN >> 24) & 0x0F)) || (timeout_in_seconds >= 10*(settingsGetPointer()->timeoutMenuEdit))) - { - exitMenuEdit_to_Home(); - timeout_in_seconds = 0; - } - } - break; - - case BaseInfo: - if((timeout_in_seconds >= settingsGetPointer()->timeoutInfo) || modeChange) - { - if(status.page == InfoPageLogList) - { - exitLog(); - timeout_in_seconds = 0; - } - else - if(status.page == InfoPageLogShow) - { - show_logbook_exit(); - exitLog(); - timeout_in_seconds = 0; - } - else - if(status.page != InfoPageCompass) - { - exitInfo(); - timeout_in_seconds = 0; - } - } - break; - default: - break; - } - } + TimeoutControlRequestModechange(); } - - get_globalStateList(&status); - if(status.base == BaseComm) /* main loop not serviced in com mode */ { tComm_refresh(); @@ -1045,6 +919,8 @@ /* not at the moment of testing */ // ext_flash_erase_firmware_if_not_empty(); GFX_logoAutoOff(); + ext_flash_write_devicedata(true); /* write data at default position */ + ext_flash_write_settings(true); /* write data at default position */ set_globalState(StStop); } @@ -1754,6 +1630,155 @@ HAL_NVIC_SystemReset(); } +static void TimeoutControlRequestModechange(void) +{ + RequestModeChange = 1; +} + +static void TimeoutControl(void) +{ + static uint8_t last_base; + + SStateList status; + uint32_t timeout_in_seconds; + uint32_t timeout_limit_Surface_in_seconds; + _Bool InDiveMode = 0; + + get_globalStateList(&status); + + if(stateUsed->mode == MODE_DIVE) + { + InDiveMode = 1; + } + else + { + InDiveMode = 0; + } + /* timeout control */ + if(RequestModeChange) ///< from RTE, set in data_exchange_main.c + time_without_button_pressed_deciseconds = (settingsGetPointer()->timeoutSurfacemode / 4) * 3; + if(status.base != last_base) + time_without_button_pressed_deciseconds = 0; + last_base = status.base; + timeout_in_seconds = time_without_button_pressed_deciseconds / 10; + time_without_button_pressed_deciseconds += 1; + if(RequestModeChange || (timeout_in_seconds != time_without_button_pressed_deciseconds / 10)) + { + #ifdef NO_TIMEOUT + timeout_in_seconds = 0; + #else + timeout_in_seconds += 1; + #endif + + if(InDiveMode) + { + switch(status.base) + { + case BaseHome: + if((status.line != 0) && (timeout_in_seconds >= settingsGetPointer()->timeoutEnterButtonSelectDive)) + { + set_globalState(StD); + timeout_in_seconds = 0; + } + break; + + case BaseMenu: + if((status.line == 0) && ((timeout_in_seconds >= settingsGetPointer()->timeoutMenuDive) || RequestModeChange)) + { + exitMenu(); + timeout_in_seconds = 0; + } + if((status.line != 0) && ((timeout_in_seconds >= settingsGetPointer()->timeoutMenuEdit) || RequestModeChange)) + { + exitMenuEdit_to_Home(); + timeout_in_seconds = 0; + } + break; + default: + break; + } + } + else /* surface mode */ + { + switch(status.base) + { + case BaseHome: + // added hw 161027 + if(!(stateRealGetPointer()->warnings.lowBattery) && (stateRealGetPointer()->lifeData.battery_charge > 9)) + { + stateRealGetPointerWrite()->lastKnownBatteryPercentage = stateRealGetPointer()->lifeData.battery_charge; + } + else if((wasFirmwareUpdateCheckBattery) && (timeout_in_seconds > 3)) + { + wasFirmwareUpdateCheckBattery = 0; + setButtonResponsiveness(settingsGetPointer()->ButtonResponsiveness); // added 170306 + if( (settingsGetPointer()->lastKnownBatteryPercentage > 0) + && (settingsGetPointer()->lastKnownBatteryPercentage <= 100) + && (stateRealGetPointer()->warnings.lowBattery)) + { + setBatteryPercentage(settingsGetPointer()->lastKnownBatteryPercentage); + } + } + // stuff before and new @161121 CCR-sensor limit 10 minutes + if((settingsGetPointer()->dive_mode == DIVEMODE_CCR) && (settingsGetPointer()->CCR_Mode == CCRMODE_Sensors)) + { + timeout_limit_Surface_in_seconds = settingsGetPointer()->timeoutSurfacemodeWithSensors; + } + else + { + timeout_limit_Surface_in_seconds = settingsGetPointer()->timeoutSurfacemode; + } + if(timeout_in_seconds >= timeout_limit_Surface_in_seconds) + { + gotoSleep(); + } + break; + case BaseMenu: + if((status.line == 0) && ((timeout_in_seconds >= settingsGetPointer()->timeoutMenuSurface) || RequestModeChange)) + { + exitMenu(); + timeout_in_seconds = 0; + } + if((status.line != 0) && ((timeout_in_seconds >= settingsGetPointer()->timeoutMenuEdit) || RequestModeChange)) + { + if((status.page != (uint8_t)((StMPLAN >> 24) & 0x0F)) || (timeout_in_seconds >= 10*(settingsGetPointer()->timeoutMenuEdit))) + { + exitMenuEdit_to_Home(); + timeout_in_seconds = 0; + } + } + break; + + case BaseInfo: + if((timeout_in_seconds >= settingsGetPointer()->timeoutInfo) || RequestModeChange) + { + if(status.page == InfoPageLogList) + { + exitLog(); + timeout_in_seconds = 0; + } + else + if(status.page == InfoPageLogShow) + { + show_logbook_exit(); + exitLog(); + timeout_in_seconds = 0; + } + else + if(status.page != InfoPageCompass) + { + exitInfo(); + timeout_in_seconds = 0; + } + } + break; + default: + break; + } + } + } + RequestModeChange = 0; +} // debugging by https://blog.feabhas.com/2013/02/developing-a-generic-hard-fault-handler-for-arm-cortex-m3cortex-m4/ /* diff -r c2264ce139cb -r 30580cf5ee77 Discovery/Src/data_exchange_main.c --- a/Discovery/Src/data_exchange_main.c Mon Feb 10 08:23:15 2020 +0000 +++ b/Discovery/Src/data_exchange_main.c Tue Feb 18 07:20:29 2020 +0000 @@ -640,7 +640,7 @@ if(dataLengthRead == 0) { - ext_flash_write_devicedata(); + ext_flash_write_devicedata(false); return; } @@ -682,7 +682,7 @@ } DataEX_check_DeviceData (); - ext_flash_write_devicedata(); + ext_flash_write_devicedata(false); } diff -r c2264ce139cb -r 30580cf5ee77 Discovery/Src/externLogbookFlash.c --- a/Discovery/Src/externLogbookFlash.c Mon Feb 10 08:23:15 2020 +0000 +++ b/Discovery/Src/externLogbookFlash.c Tue Feb 18 07:20:29 2020 +0000 @@ -116,14 +116,17 @@ /* Private variables ---------------------------------------------------------*/ static uint32_t actualAddress = 0; +static uint32_t preparedPageAddress = 0; +static uint32_t closeSectorAddress = 0; static uint32_t entryPoint = 0; static uint32_t actualPointerHeader = 0; static uint32_t actualPointerSample = 0; static uint32_t LengthLeftSampleRead = 0; -static uint32_t actualPointerDevicedata = 0; +static uint32_t actualPointerDevicedata = DDSTART; +static uint32_t actualPointerDevicedata_Read = DDSTART; static uint32_t actualPointerVPM = 0; -static uint32_t actualPointerSettings = 0; +static uint32_t actualPointerSettings = SETTINGSSTART; static uint32_t actualPointerFirmware = 0; static uint32_t actualPointerFirmware2 = 0; @@ -392,18 +395,24 @@ #ifndef BOOTLOADER_STANDALONE -void ext_flash_write_devicedata(void) +void ext_flash_write_devicedata(uint8_t resetRing) { uint8_t *pData; const uint16_t length = sizeof(SDevice); uint8_t length_lo, length_hi; uint8_t dataLength[2] = { 0 }; + uint32_t tmpBlockStart; ext_flash_disable_protection(); pData = (uint8_t *)stateDeviceGetPointer(); - actualPointerDevicedata = DDSTART; + /* Reset the Ring to the start address if requested (e.g. because we write the default block during shutdown) */ + if((resetRing) || ((actualPointerDevicedata + length) >= DDSTOP)) + { + actualPointerDevicedata = DDSTART; + } + tmpBlockStart = actualPointerDevicedata; length_lo = (uint8_t)(length & 0xFF); length_hi = (uint8_t)(length >> 8); @@ -412,6 +421,9 @@ ef_write_block(dataLength,2, EF_DEVICEDATA, 0); ef_write_block(pData,length, EF_DEVICEDATA, 0); + + actualPointerDevicedata_Read = tmpBlockStart; + } @@ -420,20 +432,37 @@ uint16_t length; uint8_t length_lo, length_hi; - actualAddress = DDSTART; + actualAddress = actualPointerDevicedata_Read; + length = 0; + length_lo = 0; + length_hi = 0; ext_flash_read_block_start(); + + ext_flash_read_block(&length_lo, EF_DEVICEDATA); ext_flash_read_block(&length_hi, EF_DEVICEDATA); - length = (length_hi * 256) + length_lo; - - if(length > max_length) - return 0; - - ext_flash_read_block_multi(buffer,length,EF_DEVICEDATA); + while ((length_lo != 0xFF) && (length_hi != 0xFF)) + { + length = (length_hi * 256) + length_lo; + + if(length > max_length) + return 0; + + ext_flash_read_block_multi(buffer,length,EF_DEVICEDATA); + + ext_flash_read_block(&length_lo, EF_DEVICEDATA); /* check if another devicedata set is available */ + ext_flash_read_block(&length_hi, EF_DEVICEDATA); /* length will be 0xFFFF if a empty memory is read */ + } + ext_flash_decf_address_ring(EF_DEVICEDATA); /* set pointer back to empty address */ + ext_flash_decf_address_ring(EF_DEVICEDATA); ext_flash_read_block_stop(); - + + if(actualAddress > actualPointerDevicedata) /* the write pointer has not yet been set up probably */ + { + actualPointerDevicedata = actualAddress; + } return length; } @@ -493,7 +522,7 @@ return; } #else -void ext_flash_write_settings(void) +void ext_flash_write_settings(uint8_t resetRing) { uint8_t *pData; const uint16_t length = sizeof(SSettings); @@ -511,7 +540,11 @@ pData = (uint8_t *)settingsGetPointer(); - actualPointerSettings = SETTINGSSTART; + /* Reset the Ring to the start address if requested (e.g. because we write the default block during shutdown) */ + if((resetRing) || ((actualPointerSettings + length) >= SETTINGSSTOP)) + { + actualPointerSettings = SETTINGSSTART; + } length_lo = (uint8_t)(length & 0xFF); length_hi = (uint8_t)(length >> 8); @@ -548,23 +581,36 @@ ext_flash_read_block(&length_lo, EF_SETTINGS); ext_flash_read_block(&length_hi, EF_SETTINGS); - lengthOnEEPROM = length_hi * 256; - lengthOnEEPROM += length_lo; - if(lengthOnEEPROM <= lengthStandardNow) + while ((length_lo != 0xFF) && (length_hi != 0xFF)) /* get the latest stored setting block */ { - ext_flash_read_block_multi(&header, 4, EF_SETTINGS); - if((header <= pSettings->header) && (header >= pSettings->updateSettingsAllowedFromHeader)) + lengthOnEEPROM = length_hi * 256; + lengthOnEEPROM += length_lo; + if(lengthOnEEPROM <= lengthStandardNow) { - returnValue = HAL_OK; - pSettings->header = header; - pData = (uint8_t *)pSettings + 4; /* header */ - for(uint16_t i = 0; i < (lengthOnEEPROM-4); i++) - ext_flash_read_block(&pData[i], EF_SETTINGS); + ext_flash_read_block_multi(&header, 4, EF_SETTINGS); + if((header <= pSettings->header) && (header >= pSettings->updateSettingsAllowedFromHeader)) + { + returnValue = HAL_OK; + pSettings->header = header; + pData = (uint8_t *)pSettings + 4; /* header */ + for(uint16_t i = 0; i < (lengthOnEEPROM-4); i++) + ext_flash_read_block(&pData[i], EF_SETTINGS); + } + else + { + returnValue = HAL_ERROR; + } } - else - { - returnValue = HAL_ERROR; - } + ext_flash_read_block(&length_lo, EF_SETTINGS); + ext_flash_read_block(&length_hi, EF_SETTINGS); + } + ext_flash_decf_address_ring(EF_SETTINGS); /* set pointer back to empty address */ + ext_flash_decf_address_ring(EF_SETTINGS); + ext_flash_read_block_stop(); + + if(actualAddress > actualPointerSettings) /* the write pointer has not yet been set up probably */ + { + actualPointerSettings = actualAddress; } ext_flash_read_block_stop(); return returnValue; @@ -614,7 +660,7 @@ void ext_flash_create_new_dive_log(uint8_t *pHeaderPreDive) { SSettings *settings; - uint8_t id, id_next; + uint8_t id; uint8_t header1, header2; settings = settingsGetPointer(); @@ -622,10 +668,12 @@ actualAddress = HEADERSTART + (0x800 * id); ext_flash_read_block_start(); - ext_flash_read_block(&header1, EF_SAMPLE); - ext_flash_read_block(&header2, EF_SAMPLE); + ext_flash_read_block(&header1, EF_SAMPLE); /* the sample ring is increased instead of header... not sure if that is planned intention */ + ext_flash_read_block(&header2, EF_SAMPLE); /* does not matter because actual address is reset in write_block call */ ext_flash_read_block_stop(); + /* TODO Cleanup_Ref_2: The code below should not be necessary in case of a proper shutdown and startup */ + /* the implementation fixes an issue which might happen at Cleanup_Ref_1 (in case of more then 254 dives) */ if((header1 == 0xFA) && (header2 == 0xFA)) { id += 1; /* 0-255, auto rollover */ @@ -645,11 +693,6 @@ id = 0; } - /* delete next header */ - id_next = id + 1; - actualPointerHeader = HEADERSTART + (0x800 * id_next); - ef_write_block(0,0, EF_HEADER, 0); - settings->lastDiveLogId = id; actualPointerHeader = HEADERSTART + (0x800 * id); @@ -726,10 +769,28 @@ void ext_flash_write_sample(uint8_t *pSample, uint16_t length) { + uint32_t actualAdressBackup = 0; + ef_write_block(pSample,length, EF_SAMPLE, 0); SSettings *settings = settingsGetPointer(); settings->logFlashNextSampleStartAddress = actualPointerSample; + + if(0xFFFF - (actualAddress & 0x0000FFFF) < 255) /* are we close to a sector border? */ + { + if (((actualAddress & 0x0000FFFF) != 0) && (preparedPageAddress == 0)) /* only prepare if not already at start of sector */ + { + actualAdressBackup = actualAddress; + actualAddress = (actualAddress & 0xFFFF0000) + 0x00010000; /* Set to start of next 64k sector */ + if(actualAddress >= SAMPLESTOP) + { + actualAddress = SAMPLESTART; + } + preparedPageAddress = actualAddress; + ext_flash_erase64kB(); + actualAddress = actualAdressBackup; + } + } } static void ext_flash_overwrite_sample_without_erase(uint8_t *pSample, uint16_t length) @@ -1316,16 +1377,16 @@ ext_flash_read_block(&dataStart.u8bit.byteMidLow, EF_HEADER); ext_flash_read_block(&dataStart.u8bit.byteMidHigh, EF_HEADER); ext_flash_read_block_stop(); - if((header1 == 0xFA) && (header2 == 0xFA)) + if((header1 == 0xFA) && (header2 == 0xFA)) /* Header is indicating the start of a dive */ { actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET; ext_flash_read_block_start(); ext_flash_read_block(&header1, EF_HEADER); ext_flash_read_block(&header2, EF_HEADER); ext_flash_read_block_stop(); - if((header1 != 0xFA) || (header2 != 0xFA)) + if((header1 != 0xFA) || (header2 != 0xFA)) /* Secondary header was not written at the end of a dive */ { - actualPointerSample = dataStart.u32bit; + actualPointerSample = dataStart.u32bit; /* Set datapointer to position stored in header written at beginning of dive */ actualAddress = actualPointerSample; logbook_recover_brokenlog(id); SSettings *settings = settingsGetPointer(); @@ -1343,6 +1404,9 @@ uint8_t header1, header2; convert_Type dataStart, dataEnd; + /* TODO Cleanup_Ref_1: cleanup logFlashNextSampleStartAddress and lastDiveLogId */ + /* The implementation below would cause problems in case more then 254 dives would be done. */ + /* This is avoided by Cleanup_Ref2 */ for(id = 0; id < 255;id++) { actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET; @@ -1578,7 +1642,7 @@ ext_flash_erase4kB(); return 1; } - } + } else if(actualAddress < 0x00010000) { @@ -1588,16 +1652,25 @@ ext_flash_erase32kB(); return 1; } - } + } else { /* 64K Byte is 0x10000 */ if((actualAddress & 0xFFFF) == 0) { - ext_flash_erase64kB(); + if(preparedPageAddress == actualAddress) /* has page already been prepared before? (at the moment for samples only) */ + { + preparedPageAddress = 0; + + } + else + { + ext_flash_erase64kB(); + } return 1; } - } + } + return 0; } @@ -1633,7 +1706,8 @@ static void ef_write_block(uint8_t * sendByte, uint32_t length, uint8_t type, uint8_t do_not_erase) { uint32_t remaining_page_size, remaining_length, remaining_space_to_ring_end; - + uint32_t i=0; + if(!length) return; @@ -1688,7 +1762,7 @@ if(do_not_erase == 0) ext_flash_erase_if_on_page_start(); - for(uint32_t i=0;i= 256) && (remaining_space_to_ring_end >= 256)) + if(remaining_length >= 256) + { + remaining_length = 255; /* up to 256 bytes may be written in one burst. Last byte is written with release */ + } + else { - for(int j=0; j<255; j++) + remaining_length--; /* last byte needed for release */ + } + if(remaining_length >= (remaining_page_size) ) /* use 256 byte page and calculate number of bytes left */ + { + remaining_length = remaining_page_size - 1; + } + if( (remaining_space_to_ring_end >= 256)) + { + for(int j=0; j ringStop) actualAddress = ringStart; + if(do_not_erase == 0) ext_flash_erase_if_on_page_start(); } @@ -2026,6 +2115,131 @@ { } } + +void ext_flash_CloseSector(void) +{ + uint32_t actualAddressBackup = actualAddress; + int i=0; + + if(closeSectorAddress != 0) + { + /* write some dummy bytes to the sector which is currently used for storing samples. This is done to "hide" problem if function is calles again */ + actualAddress = closeSectorAddress; + + wait_chip_not_busy(); + write_spi(0x06,RELEASE); /* WREN */ + write_spi(0x02,HOLDCS); /* write cmd */ + write_address(HOLDCS); + for(i = 0; i<8; i++) + { + write_spi(0xA5,HOLDCS);/* write data */ + actualAddress++; + } + /* byte with RELEASE */ + write_spi(0xA5,RELEASE);/* write data */ + actualAddress = actualAddressBackup; + closeSectorAddress = 0; + } +} + +uint32_t ext_flash_AnalyseSampleBuffer(char *pstrResult) +{ + uint8_t sectorState[16]; /* samples are stored in 16 sector / 64k each */ + uint32_t curAddress = SAMPLESTART; + uint8_t curSector = 0; + uint8_t samplebuffer[10]; + uint32_t actualAddressBackup = actualAddress; + uint8_t emptyCellCnt = 0; + uint32_t i = 0; + uint8_t startedSectors = 0; + uint8_t lastSectorInuse = 0; + +/* check if a sector is used till its end */ + for(curSector = 0; curSector < 16; curSector++) + { + sectorState[curSector] = 0; + emptyCellCnt = 0; + curAddress = SAMPLESTART + (curSector * 0x10000); /* set address to begin of sector and check if it is used */ + actualAddress = curAddress; + ext_flash_read_block_start(); + for(uint32_t i=0;i<10;i++) + { + samplebuffer[i] = read_spi(HOLDCS);/* read data */ + if(samplebuffer[i] == 0xFF) + { + emptyCellCnt++; + } + } + ext_flash_read_block_stop(); + if(emptyCellCnt == 10) + { + sectorState[curSector] = SECTOR_NOTUSED; + } + emptyCellCnt = 0; + curAddress = SAMPLESTART + (curSector * 0x10000) + 0xFFF5; /* set address to end of sector and check if it is used */ + actualAddress = curAddress; + ext_flash_read_block_start(); + for(i=0;i<10;i++) + { + samplebuffer[i] = read_spi(HOLDCS);/* read data */ + if(samplebuffer[i] == 0xFF) + { + emptyCellCnt++; + } + } + ext_flash_read_block_stop(); + if(emptyCellCnt == 10) + { + sectorState[curSector] |= SECTOR_INUSE; /* will become SECTOR_EMPTY if start is NOTUSED */ + } + } + + for(i=0;i<16;i++) + { + if( sectorState[i] == SECTOR_INUSE) + { + startedSectors++; + lastSectorInuse = i; + } + *(pstrResult+i) = sectorState[i] + 48; + } + + if(startedSectors > 1) /* more than one sector is in used => ring buffer corrupted */ + { + if(startedSectors == 2) /* only fix issue if only two sectors are in used. Otherwise fixing will cause more worries than help */ + { + /* the logic behind healing of the problem is that the larger address is the oldest one => restore the largest address */ + curAddress = SAMPLESTART + (lastSectorInuse * 0x10000); + emptyCellCnt = 0; + actualAddress = curAddress; + ext_flash_read_block_start(); + while((emptyCellCnt < 10) && (actualAddress < curAddress + 0x10000)) + { + samplebuffer[0] = read_spi(HOLDCS);/* read data */ + if(samplebuffer[0] == 0xFF) + { + emptyCellCnt++; + } + else + { + emptyCellCnt = 0; + } + actualAddress++; + } + ext_flash_read_block_stop(); + actualAddress -= 10; /* step 10 bytes back to the start of free bytes */ + actualPointerSample = actualAddress; + + closeSectorAddress = settingsGetPointer()->logFlashNextSampleStartAddress & 0xFFFF0000; + closeSectorAddress += 0xFFF5; /* to be used once next time a dive is logged. Needed because NextSampleID is derived at every startup */ + settingsGetPointer()->logFlashNextSampleStartAddress = actualPointerSample; /* store new position to be used for next dive */ + } + } + actualAddress = actualAddressBackup; + *(pstrResult+i) = 0; + return startedSectors; +} + /* uint8_t ext_flash_erase_firmware_if_not_empty(void) { diff -r c2264ce139cb -r 30580cf5ee77 Discovery/Src/logbook.c --- a/Discovery/Src/logbook.c Mon Feb 10 08:23:15 2020 +0000 +++ b/Discovery/Src/logbook.c Tue Feb 18 07:20:29 2020 +0000 @@ -1187,8 +1187,10 @@ { pSettings->logbookOffset++; } - ext_flash_write_settings(); + ext_flash_write_settings(0); ext_flash_disable_protection_for_logbook(); + + ext_flash_CloseSector(); /* this is just a repair function which invalidates a not used sector in case a log maintenance was called before dive */ bDiveMode = 3; } if(bDiveMode == 3) diff -r c2264ce139cb -r 30580cf5ee77 Discovery/Src/tMenuEdit.c --- a/Discovery/Src/tMenuEdit.c Mon Feb 10 08:23:15 2020 +0000 +++ b/Discovery/Src/tMenuEdit.c Tue Feb 18 07:20:29 2020 +0000 @@ -272,7 +272,7 @@ if(WriteSettings) { GFX_logoAutoOff(); - ext_flash_write_settings(); + ext_flash_write_settings(0); WriteSettings = 0; } } diff -r c2264ce139cb -r 30580cf5ee77 Discovery/Src/tMenuEditSystem.c --- a/Discovery/Src/tMenuEditSystem.c Mon Feb 10 08:23:15 2020 +0000 +++ b/Discovery/Src/tMenuEditSystem.c Tue Feb 18 07:20:29 2020 +0000 @@ -41,6 +41,8 @@ #include "motion.h" #include "t7.h" +/* Uncomment to activate a menu item in reset menu which provide sample ring analysis / repair functionality */ +#define ENABLE_ANALYSE_SAMPLES #define CV_SUBPAGE_MAX (2u) /* max number of customer view selection pages */ /*#define HAVE_DEBUG_VIEW */ @@ -95,6 +97,7 @@ uint8_t OnAction_LogbookOffset(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_SetFactoryDefaults(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); uint8_t OnAction_SetBatteryCharge(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); +uint8_t OnAction_RecoverSampleIdx(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); #ifdef SCREENTEST uint8_t OnAction_ScreenTest (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action); #endif @@ -1470,27 +1473,46 @@ case StMSYS6_Maintenance: case StMSYS6_SetBattCharge: + case StMSYS6_SetSampleIndx: text[0] = TXT_2BYTE; text[1] = TXT2BYTE_SetFactoryDefaults; text[2] = 0; write_field_button(StMSYS6_SetFactoryBC, 30, 800, ME_Y_LINE2, &FontT48, text); +#ifdef ENABLE_ANALYSE_SAMPLES + text[0] = TXT_2BYTE; + text[1] = TXT2BYTE_SetSampleIndex; + text[2] = 0; + write_field_button(StMSYS6_SetSampleIndx, 30, 800, ME_Y_LINE3, &FontT48, text); +#endif + + if(stateRealGetPointer()->lifeData.battery_charge == 0) { text[0] = TXT_2BYTE; text[1] = TXT2BYTE_SetBatteryCharge; text[2] = 0; snprintf(&text[2],10,": %u%%",settingsGetPointer()->lastKnownBatteryPercentage); +#ifdef ENABLE_ANALYSE_SAMPLES + write_field_button(StMSYS6_SetBattCharge, 30, 800, ME_Y_LINE4, &FontT48, text); +#else write_field_button(StMSYS6_SetBattCharge, 30, 800, ME_Y_LINE3, &FontT48, text); +#endif setEvent(StMSYS6_Exit, (uint32_t)OnAction_Exit); setEvent(StMSYS6_SetFactoryBC, (uint32_t)OnAction_SetFactoryDefaults); +#ifdef ENABLE_ANALYSE_SAMPLES + setEvent(StMSYS6_SetSampleIndx, (uint32_t)OnAction_RecoverSampleIdx); +#endif setEvent(StMSYS6_SetBattCharge, (uint32_t)OnAction_SetBatteryCharge); } else { setEvent(StMSYS6_Exit, (uint32_t)OnAction_Exit); setEvent(StMSYS6_SetFactoryBC, (uint32_t)OnAction_SetFactoryDefaults); +#ifdef ENABLE_ANALYSE_SAMPLES + setEvent(StMSYS6_SetSampleIndx, (uint32_t)OnAction_RecoverSampleIdx); +#endif } // write_field_button(StMSYS6_ScreenTest, 30, 800, ME_Y_LINE3, &FontT48, "Screen Test"); // setEvent(StMSYS6_ScreenTest, (uint32_t)OnAction_ScreenTest); @@ -1609,6 +1631,18 @@ } +uint8_t OnAction_RecoverSampleIdx(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) +{ + char text[32]; + char strResult[20]; + + + ext_flash_AnalyseSampleBuffer(strResult); + snprintf(&text[0],30,"Ring: %s",strResult); //"Code: %X",settingsGetPointer()->logFlashNextSampleStartAddress); //getLicence()); + write_label_var( 30, 800, ME_Y_LINE6, &FontT42, text); + return UNSPECIFIC_RETURN; +} + uint8_t OnAction_SetBatteryCharge(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) { setBatteryPercentage(settingsGetPointer()->lastKnownBatteryPercentage); diff -r c2264ce139cb -r 30580cf5ee77 Discovery/Src/text_multilanguage.c --- a/Discovery/Src/text_multilanguage.c Mon Feb 10 08:23:15 2020 +0000 +++ b/Discovery/Src/text_multilanguage.c Tue Feb 18 07:20:29 2020 +0000 @@ -618,6 +618,14 @@ static uint8_t text_ES_SetFactoryDefaults[] = "Restablecer ajustes de fábrica"; // Menu SYS2 sub +static uint8_t text_EN_SetSampleIndex[] = "Analyse log memory"; +static uint8_t text_DE_SetSampleIndex[] = "Prüfe Logbuchspeicher"; +static uint8_t text_FR_SetSampleIndex[] = "Maintain log memory"; +static uint8_t text_IT_SetSampleIndex[] = "Maintain log memory"; +static uint8_t text_ES_SetSampleIndex[] = "Maintain log memory"; + + +// Menu SYS2 sub static uint8_t text_EN_Reboot[] = "Reboot"; static uint8_t text_DE_Reboot[] = "Neustart"; static uint8_t text_FR_Reboot[] = "Redémarrage"; @@ -1761,6 +1769,7 @@ {(uint8_t)TXT2BYTE_Maintenance, {text_EN_Maintenance, text_DE_Maintenance, text_FR_Maintenance, text_IT_Maintenance, text_ES_Maintenance}}, {(uint8_t)TXT2BYTE_SetBatteryCharge,{text_EN_SetBatteryCharge, text_DE_SetBatteryCharge, text_FR_SetBatteryCharge, text_IT_SetBatteryCharge, text_ES_SetBatteryCharge}}, {(uint8_t)TXT2BYTE_SetFactoryDefaults,{text_EN_SetFactoryDefaults, text_DE_SetFactoryDefaults, text_FR_SetFactoryDefaults, text_IT_SetFactoryDefaults, text_ES_SetFactoryDefaults}}, + {(uint8_t)TXT2BYTE_SetSampleIndex, {text_EN_SetSampleIndex, text_DE_SetSampleIndex, text_FR_SetSampleIndex, text_IT_SetSampleIndex, text_ES_SetSampleIndex}}, {(uint8_t)TXT2BYTE_Reboot, {text_EN_Reboot, text_DE_Reboot, text_FR_Reboot, text_IT_Reboot, text_ES_Reboot}}, {(uint8_t)TXT2BYTE_ButtonLeft, {text_EN_ButtonLeft, text_DE_ButtonLeft, text_FR_ButtonLeft, text_IT_ButtonLeft, text_ES_ButtonLeft}},