Implemented CRC of persistent data (settings and VFO state) in MDx devices

pull/103/head
Silvano Seva 2022-08-11 17:02:04 +02:00
rodzic 4b0326b1c8
commit e2137eae23
12 zmienionych plików z 86 dodań i 127 usunięć

Wyświetl plik

@ -57,7 +57,7 @@ void nvm_readCalibData(void *buf);
*
* @param info: destination data structure for hardware information data.
*/
void nvm_loadHwInfo(hwInfo_t *info);
void nvm_readHwInfo(hwInfo_t *info);
/**
* Read from storage the channel data corresponding to the VFO channel A.
@ -65,7 +65,7 @@ void nvm_loadHwInfo(hwInfo_t *info);
* @param channel: pointer to the channel_t data structure to be populated.
* @return 0 on success, -1 on failure
*/
int nvm_readVFOChannelData(channel_t *channel);
int nvm_readVfoChannelData(channel_t *channel);
/**
* Read OpenRTX settings from storage.

Wyświetl plik

@ -26,7 +26,7 @@ channel_t cps_getDefaultChannel()
channel_t channel;
channel.mode = OPMODE_FM;
channel.bandwidth = BW_25;
channel.power = 1.0;
channel.power = 100; // 1W, P = 10dBm + n*0.2dBm, we store n
// Set initial frequency based on supported bands
const hwInfo_t* hwinfo = platform_getHwInfo();

Wyświetl plik

@ -48,7 +48,7 @@ void state_init()
* Try loading VFO configuration from nonvolatile memory and default to sane
* values in case of failure.
*/
if(nvm_readVFOChannelData(&state.channel) < 0)
if(nvm_readVfoChannelData(&state.channel) < 0)
{
state.channel = cps_getDefaultChannel();
}

Wyświetl plik

@ -40,8 +40,11 @@ static const uint32_t VHF_CAL_BASE = 0x6F070;
/**
* \internal Utility function for loading band-specific calibration data into
* the corresponding data structure.
*
* @param baseAddr: start address of the data block;
* @param cal: pointer to calibration data structure to be filled.
*/
void _loadBandCalData(uint32_t baseAddr, bandCalData_t *cal)
static void _loadBandCalData(uint32_t baseAddr, bandCalData_t *cal)
{
W25Qx_readData(baseAddr + 0x08, &(cal->modBias), 2);
W25Qx_readData(baseAddr + 0x0A, &(cal->mod2Offset), 1);
@ -87,6 +90,7 @@ void _loadBandCalData(uint32_t baseAddr, bandCalData_t *cal)
}
}
void nvm_init()
{
W25Qx_init();
@ -133,13 +137,13 @@ void nvm_readCalibData(void *buf)
calib->vhfCalPoints[7] = 172000000;
}
void nvm_loadHwInfo(hwInfo_t *info)
void nvm_readHwInfo(hwInfo_t *info)
{
/* GDx devices does not have any hardware info in the external flash. */
(void) info;
}
int nvm_readVFOChannelData(channel_t *channel)
int nvm_readVfoChannelData(channel_t *channel)
{
(void) channel;
return -1;

Wyświetl plik

@ -96,7 +96,7 @@ void nvm_readCalibData(void *buf)
}
}
void nvm_loadHwInfo(hwInfo_t *info)
void nvm_readHwInfo(hwInfo_t *info)
{
uint16_t freqMin = 0;
uint16_t freqMax = 0;
@ -142,32 +142,10 @@ void nvm_loadHwInfo(hwInfo_t *info)
}
/**
* The MD380 stock CPS does not have a VFO channel slot
* because the stock firmware does not have a VFO
* To enable this functionality reserve a Flash portion for saving the VFO
*
* TODO: temporarily implemented in "nvmem_settings_MDx.c"
* TODO: functions temporarily implemented in "nvmem_settings_MDx.c"
int nvm_readVFOChannelData(channel_t *channel)
{
(void) channel;
return -1;
}
*/
/*
TODO: temporarily implemented in "nvmem_settings_MDx.c"
int nvm_readSettings(settings_t *settings)
{
(void) settings;
return -1;
}
*/
int nvm_writeSettings(const settings_t *settings)
{
(void) settings;
return -1;
}
*/

Wyświetl plik

@ -42,36 +42,16 @@ void nvm_readCalibData(void *buf)
return;
}
/*
TODO: temporarily implemented in "nvmem_settings_MDx.c"
void nvm_readHwInfo(hwInfo_t *info)
{
(void) info;
}
/**
* TODO: functions temporarily implemented in "nvmem_settings_MDx.c"
int nvm_readVFOChannelData(channel_t *channel)
{
return _cps_readChannelAtAddress(channel, vfoChannelBaseAddr);
}
*/
/*
TODO: temporarily implemented in "nvmem_settings_MDx.c"
int nvm_readSettings(settings_t *settings)
{
settings_t newSettings;
W25Qx_wakeup();
delayUs(5);
W25Qx_readData(settingsAddr, ((uint8_t *) &newSettings), sizeof(settings_t));
W25Qx_sleep();
if(memcmp(newSettings.valid, default_settings.valid, 6) != 0)
return -1;
memcpy(settings, &newSettings, sizeof(settings_t));
return 0;
}
*/
int nvm_writeSettings(const settings_t *settings)
{
// Disable settings write until DFU is implemented for flash backups
(void) settings;
return -1;
}
*/

Wyświetl plik

@ -104,7 +104,7 @@ void nvm_readCalibData(void *buf)
}
}
void nvm_loadHwInfo(hwInfo_t *info)
void nvm_readHwInfo(hwInfo_t *info)
{
uint16_t vhf_freqMin = 0;
uint16_t vhf_freqMax = 0;
@ -142,35 +142,11 @@ void nvm_loadHwInfo(hwInfo_t *info)
info->lcd_type = lcdInfo & 0x03;
}
/*
TODO: temporarily implemented in "nvmem_settings_MDx.c"
/**
* TODO: functions temporarily implemented in "nvmem_settings_MDx.c"
int nvm_readVFOChannelData(channel_t *channel)
{
return _cps_readChannelAtAddress(channel, vfoChannelBaseAddr);
}
*/
/*
TODO: temporarily implemented in "nvmem_settings_MDx.c"
int nvm_readSettings(settings_t *settings)
{
settings_t newSettings;
W25Qx_wakeup();
delayUs(5);
W25Qx_readData(settingsAddr, ((uint8_t *) &newSettings), sizeof(settings_t));
W25Qx_sleep();
if(memcmp(newSettings.valid, default_settings.valid, 6) != 0)
return -1;
memcpy(settings, &newSettings, sizeof(settings_t));
return 0;
}
*/
int nvm_writeSettings(const settings_t *settings)
{
(void) settings;
// Disable settings write until DFU is implemented for flash backups
return -1;
}
*/

Wyświetl plik

@ -35,12 +35,12 @@ void nvm_readCalibData(void *buf)
(void) buf;
}
void nvm_loadHwInfo(hwInfo_t *info)
void nvm_readHwInfo(hwInfo_t *info)
{
(void) info;
}
int nvm_readVFOChannelData(channel_t *channel)
int nvm_readVfoChannelData(channel_t *channel)
{
// Module 17 has no channels: just load default values for it
channel->mode = OPMODE_M17;

Wyświetl plik

@ -223,13 +223,13 @@ void nvm_terminate()
}
}
void nvm_loadHwInfo(hwInfo_t *info)
void nvm_readHwInfo(hwInfo_t *info)
{
/* Linux devices does not have any hardware info in the external flash. */
(void) info;
}
int nvm_readVFOChannelData(channel_t *channel)
int nvm_readVfoChannelData(channel_t *channel)
{
return _cps_read(memory_paths[P_VFO], channel, sizeof(channel_t));
}

Wyświetl plik

@ -18,29 +18,33 @@
* along with this program; if not, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#include <string.h>
#include <interfaces/nvmem.h>
#include <string.h>
#include <cps.h>
#include <crc.h>
#include "flash.h"
/*
* Data structure defining the memory layout used for saving and restore
* Data structures defining the memory layout used for saving and restore
* of user settings and VFO configuration.
*/
typedef struct
{
uint32_t magic;
uint32_t flags[64];
struct dataBlock
{
settings_t settings;
channel_t vfoData;
}
data[2048];
uint16_t crc;
settings_t settings;
channel_t vfoData;
}
__attribute__((packed)) dataBlock_t;
typedef struct
{
uint32_t magic;
uint32_t flags[32];
dataBlock_t data[1024];
}
__attribute__((packed)) memory_t;
static const uint32_t validMagic = 0x584E504F; // "OPNX"
static const uint32_t MEM_MAGIC = 0x584E504F; // "OPNX"
static const uint32_t baseAddress = 0x080E0000;
memory_t *memory = ((memory_t *) baseAddress);
@ -53,15 +57,17 @@ memory_t *memory = ((memory_t *) baseAddress);
*
* @return number currently active data block or -1 if memory data is invalid.
*/
int findActiveBlock()
static int findActiveBlock()
{
if(memory->magic != validMagic)
{
return -1; // Invalid memory data
}
// Check for invalid memory data
if(memory->magic != MEM_MAGIC)
return -1;
uint16_t block = 0;
for(; block < 64; block++)
uint16_t bit = 0;
// Find the first 32-bit block not full of zeroes
for(; block < 32; block++)
{
if(memory->flags[block] != 0x00000000)
{
@ -69,7 +75,7 @@ int findActiveBlock()
}
}
uint16_t bit = 0;
// Find the last zero within a block
for(; bit < 32; bit++)
{
if((memory->flags[block] & (1 << bit)) != 0)
@ -79,12 +85,19 @@ int findActiveBlock()
}
block = (block * 32) + bit;
return block - 1;
block -= 1;
// Check data validity
uint16_t crc = crc_ccitt(&(memory->data[block].settings),
sizeof(settings_t) + sizeof(channel_t));
if(crc != memory->data[block].crc)
return -2;
return block;
}
int nvm_readVFOChannelData(channel_t *channel)
int nvm_readVfoChannelData(channel_t *channel)
{
int block = findActiveBlock();
@ -110,8 +123,9 @@ int nvm_readSettings(settings_t *settings)
int nvm_writeSettingsAndVfo(const settings_t *settings, const channel_t *vfo)
{
uint32_t addr = 0;
int block = findActiveBlock();
uint32_t addr = 0;
int block = findActiveBlock();
uint16_t prevCrc = 0;
/*
* Memory never initialised or save space finished: erase all the sector.
@ -122,21 +136,28 @@ int nvm_writeSettingsAndVfo(const settings_t *settings, const channel_t *vfo)
{
flash_eraseSector(11);
addr = ((uint32_t) &(memory->magic));
flash_write(addr, &validMagic, sizeof(validMagic));
flash_write(addr, &MEM_MAGIC, sizeof(MEM_MAGIC));
block = 0;
}
else
{
prevCrc = memory->data[block].crc;
block += 1;
}
// Save settings
addr = ((uint32_t) &(memory->data[block].settings));
flash_write(addr, settings, sizeof(settings_t));
dataBlock_t tmpBlock;
memcpy((&tmpBlock.settings), settings, sizeof(settings_t));
memcpy((&tmpBlock.vfoData), vfo, sizeof(channel_t));
tmpBlock.crc = crc_ccitt(&(tmpBlock.settings),
sizeof(settings_t) + sizeof(channel_t));
// Save VFO configuration
addr = ((uint32_t) &(memory->data[block].vfoData));
flash_write(addr, vfo, sizeof(channel_t));
// New data is equal to the old one, avoid saving
if((block != 0) && (tmpBlock.crc == prevCrc))
return 0;
// Save data
addr = ((uint32_t) &(memory->data[block]));
flash_write(addr, &tmpBlock, sizeof(dataBlock_t));
// Update the flags marking used data blocks
uint32_t flag = ~(1 << (block % 32));

Wyświetl plik

@ -62,7 +62,7 @@ void platform_init()
nvm_init(); /* Initialise non volatile memory manager */
nvm_readCalibData(&calibration); /* Load calibration data */
nvm_loadHwInfo(&hwInfo); /* Load hardware information data */
nvm_readHwInfo(&hwInfo); /* Load hardware information data */
toneGen_init(); /* Initialise tone generator */
rtc_init(); /* Initialise RTC */
backlight_init(); /* Initialise backlight driver */

Wyświetl plik

@ -61,7 +61,7 @@ void platform_init()
nvm_init(); /* Initialise non volatile memory manager */
nvm_readCalibData(&calibration); /* Load calibration data */
nvm_loadHwInfo(&hwInfo); /* Load hardware information data */
nvm_readHwInfo(&hwInfo); /* Load hardware information data */
toneGen_init(); /* Initialise tone generator */
rtc_init(); /* Initialise RTC */
chSelector_init(); /* Initialise channel selector handler */