comparison Discovery/Src/externLogbookFlash.c @ 425:86fcac4cc43a ImprovmentNVM_2

Added function to analyse the sampel ringbuffer: The function will show 0 for used sectors, 4 for the sector currently in use and 5 for empty sectors. This allows identification of log sample index position and identification of a buffer corruption (more than 2 sectors have state 4) The repair function writes dummy bytes to the end of the active buffer with the lower sector number. This decision is based on the fact that corruption results typically in a reset of index to buffer start address. After repair the writing will be continued using the hugher buffer marked as used.
author ideenmodellierer
date Sat, 15 Feb 2020 20:50:20 +0100
parents a560afdaadbf
children b1091e183d52
comparison
equal deleted inserted replaced
424:2b31cf1ebbcc 425:86fcac4cc43a
115 /* Exported variables --------------------------------------------------------*/ 115 /* Exported variables --------------------------------------------------------*/
116 116
117 /* Private variables ---------------------------------------------------------*/ 117 /* Private variables ---------------------------------------------------------*/
118 static uint32_t actualAddress = 0; 118 static uint32_t actualAddress = 0;
119 static uint32_t preparedPageAddress = 0; 119 static uint32_t preparedPageAddress = 0;
120 static uint32_t closeSectorAddress = 0;
120 static uint32_t entryPoint = 0; 121 static uint32_t entryPoint = 0;
121 122
122 static uint32_t actualPointerHeader = 0; 123 static uint32_t actualPointerHeader = 0;
123 static uint32_t actualPointerSample = 0; 124 static uint32_t actualPointerSample = 0;
124 static uint32_t LengthLeftSampleRead = 0; 125 static uint32_t LengthLeftSampleRead = 0;
1360 dataStart.u8bit.byteHigh = 0; 1361 dataStart.u8bit.byteHigh = 0;
1361 ext_flash_read_block(&dataStart.u8bit.byteLow, EF_HEADER); 1362 ext_flash_read_block(&dataStart.u8bit.byteLow, EF_HEADER);
1362 ext_flash_read_block(&dataStart.u8bit.byteMidLow, EF_HEADER); 1363 ext_flash_read_block(&dataStart.u8bit.byteMidLow, EF_HEADER);
1363 ext_flash_read_block(&dataStart.u8bit.byteMidHigh, EF_HEADER); 1364 ext_flash_read_block(&dataStart.u8bit.byteMidHigh, EF_HEADER);
1364 ext_flash_read_block_stop(); 1365 ext_flash_read_block_stop();
1365 if((header1 == 0xFA) && (header2 == 0xFA)) 1366 if((header1 == 0xFA) && (header2 == 0xFA)) /* Header is indicating the start of a dive */
1366 { 1367 {
1367 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET; 1368 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET;
1368 ext_flash_read_block_start(); 1369 ext_flash_read_block_start();
1369 ext_flash_read_block(&header1, EF_HEADER); 1370 ext_flash_read_block(&header1, EF_HEADER);
1370 ext_flash_read_block(&header2, EF_HEADER); 1371 ext_flash_read_block(&header2, EF_HEADER);
1371 ext_flash_read_block_stop(); 1372 ext_flash_read_block_stop();
1372 if((header1 != 0xFA) || (header2 != 0xFA)) 1373 if((header1 != 0xFA) || (header2 != 0xFA)) /* Secondary header was not written at the end of a dive */
1373 { 1374 {
1374 actualPointerSample = dataStart.u32bit; 1375 actualPointerSample = dataStart.u32bit; /* Set datapointer to position stored in header written at beginning of dive */
1375 actualAddress = actualPointerSample; 1376 actualAddress = actualPointerSample;
1376 logbook_recover_brokenlog(id); 1377 logbook_recover_brokenlog(id);
1377 SSettings *settings = settingsGetPointer(); 1378 SSettings *settings = settingsGetPointer();
1378 settings->logFlashNextSampleStartAddress = actualPointerSample; 1379 settings->logFlashNextSampleStartAddress = actualPointerSample;
1379 } 1380 }
2095 { 2096 {
2096 while(1) 2097 while(1)
2097 { 2098 {
2098 } 2099 }
2099 } 2100 }
2101
2102 void ext_flash_CloseSector(void)
2103 {
2104 uint32_t actualAddressBackup = actualAddress;
2105 int i=0;
2106
2107 if(closeSectorAddress != 0)
2108 {
2109 /* 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 */
2110 actualAddress = closeSectorAddress;
2111
2112 wait_chip_not_busy();
2113 write_spi(0x06,RELEASE); /* WREN */
2114 write_spi(0x02,HOLDCS); /* write cmd */
2115 write_address(HOLDCS);
2116 for(i = 0; i<8; i++)
2117 {
2118 write_spi(0xA5,HOLDCS);/* write data */
2119 actualAddress++;
2120 }
2121 /* byte with RELEASE */
2122 write_spi(0xA5,RELEASE);/* write data */
2123 actualAddress = actualAddressBackup;
2124 closeSectorAddress = 0;
2125 }
2126 }
2127
2128 uint32_t ext_flash_AnalyseSampleBuffer(char *pstrResult)
2129 {
2130 uint8_t sectorState[16]; /* samples are stored in 16 sector / 64k each */
2131 uint32_t curAddress = SAMPLESTART;
2132 uint8_t curSector = 0;
2133 uint8_t samplebuffer[10];
2134 uint32_t actualAddressBackup = actualAddress;
2135 uint8_t emptyCellCnt = 0;
2136 uint32_t i = 0;
2137 uint8_t startedSectors = 0;
2138 uint8_t lastSectorInuse = 0;
2139
2140 /* check if a sector is used till its end */
2141 for(curSector = 0; curSector < 16; curSector++)
2142 {
2143 sectorState[curSector] = 0;
2144 emptyCellCnt = 0;
2145 curAddress = SAMPLESTART + (curSector * 0x10000); /* set address to begin of sector and check if it is used */
2146 actualAddress = curAddress;
2147 ext_flash_read_block_start();
2148 for(uint32_t i=0;i<10;i++)
2149 {
2150 samplebuffer[i] = read_spi(HOLDCS);/* read data */
2151 if(samplebuffer[i] == 0xFF)
2152 {
2153 emptyCellCnt++;
2154 }
2155 }
2156 ext_flash_read_block_stop();
2157 if(emptyCellCnt == 10)
2158 {
2159 sectorState[curSector] = SECTOR_NOTUSED;
2160 }
2161 emptyCellCnt = 0;
2162 curAddress = SAMPLESTART + (curSector * 0x10000) + 0xFFF5; /* set address to end of sector and check if it is used */
2163 actualAddress = curAddress;
2164 ext_flash_read_block_start();
2165 for(i=0;i<10;i++)
2166 {
2167 samplebuffer[i] = read_spi(HOLDCS);/* read data */
2168 if(samplebuffer[i] == 0xFF)
2169 {
2170 emptyCellCnt++;
2171 }
2172 }
2173 ext_flash_read_block_stop();
2174 if(emptyCellCnt == 10)
2175 {
2176 sectorState[curSector] |= SECTOR_INUSE; /* will become SECTOR_EMPTY if start is NOTUSED */
2177 }
2178 }
2179
2180 for(i=0;i<16;i++)
2181 {
2182 if( sectorState[i] == SECTOR_INUSE)
2183 {
2184 startedSectors++;
2185 lastSectorInuse = i;
2186 }
2187 *(pstrResult+i) = sectorState[i] + 48;
2188 }
2189
2190 if(startedSectors > 1) /* more than one sector is in used => ring buffer corrupted */
2191 {
2192 if(startedSectors == 2) /* only fix issue if only two sectors are in used. Otherwise fixing will cause more worries than help */
2193 {
2194 /* the logic behind healing of the problem is that the larger address is the oldest one => restore the largest address */
2195 curAddress = SAMPLESTART + (lastSectorInuse * 0x10000);
2196 emptyCellCnt = 0;
2197 actualAddress = curAddress;
2198 ext_flash_read_block_start();
2199 while((emptyCellCnt < 10) && (actualAddress < curAddress + 0x10000))
2200 {
2201 samplebuffer[0] = read_spi(HOLDCS);/* read data */
2202 if(samplebuffer[0] == 0xFF)
2203 {
2204 emptyCellCnt++;
2205 }
2206 else
2207 {
2208 emptyCellCnt = 0;
2209 }
2210 actualAddress++;
2211 }
2212 ext_flash_read_block_stop();
2213 actualAddress -= 10; /* step 10 bytes back to the start of free bytes */
2214 actualPointerSample = actualAddress;
2215
2216 closeSectorAddress = settingsGetPointer()->logFlashNextSampleStartAddress & 0xFFFF0000;
2217 closeSectorAddress += 0xFFF5; /* to be used once next time a dive is logged. Needed because NextSampleID is derived at every startup */
2218 settingsGetPointer()->logFlashNextSampleStartAddress = actualPointerSample; /* store new position to be used for next dive */
2219 }
2220 }
2221 actualAddress = actualAddressBackup;
2222 *(pstrResult+i) = 0;
2223 return startedSectors;
2224 }
2225
2100 /* 2226 /*
2101 uint8_t ext_flash_erase_firmware_if_not_empty(void) 2227 uint8_t ext_flash_erase_firmware_if_not_empty(void)
2102 { 2228 {
2103 const uint8_t TESTSIZE_FW = 4; 2229 const uint8_t TESTSIZE_FW = 4;
2104 2230