kopia lustrzana https://github.com/OpenRTX/OpenRTX
Implemented CRC of persistent data (settings and VFO state) in MDx devices
rodzic
4b0326b1c8
commit
e2137eae23
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
Ładowanie…
Reference in New Issue