Например так

Код
/**
*******************************************************************************
* \file
*
* \brief Говорят что наркотики сводят с ума...
*
******************************************************************************/
#ifndef MEMORY_H
#define MEMORY_H
#include "memory_map.h"
#include "scmRTOS.h"
#include "crc-modbus.h"
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// FRAM /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#include "fram.h"
extern OS::TMutex FRAMMutex;
#define FRAM_CRC_SIZE 2 // размер CRC
//////////////////////////////// Базовый шаблон ////////////////////////////////
template <typename T, unsigned int OFFSET, unsigned int SIZEX=1, unsigned int SIZEY=1, unsigned int SIZEZ=1>
class FRAM;
//////////////////////////// Одноэлементные записи /////////////////////////////
template <typename T, unsigned int OFFSET>
class FRAM<T, OFFSET, 1, 1, 1>
{
public:
bool Get(T &t);
void Set(const T &t);
void Bad(const T &t);
};
template <typename T, unsigned int OFFSET>
bool FRAM<T, OFFSET, 1, 1, 1> :: Get(T &t)
{
unsigned short crc;
FRAMMutex.Lock();
FRAMReadBlock (FRAM_MAC, OFFSET, (uchar*)&t, sizeof(T));
FRAMReadBlock (FRAM_MAC, OFFSET + sizeof(T), (uchar*)&crc, FRAM_CRC_SIZE);
FRAMMutex.Unlock();
return (CRC16((char*)&t, sizeof(T)) == crc);
}
template <typename T, unsigned int OFFSET>
void FRAM<T, OFFSET, 1, 1, 1> :: Set(const T &t)
{
unsigned short crc;
FRAMMutex.Lock();
FRAMWriteBlock (FRAM_MAC, OFFSET, (uchar*)&t, sizeof(T));
crc = CRC16((char*)&t, sizeof(T));
FRAMWriteBlock (FRAM_MAC, OFFSET + sizeof(T), (uchar*)&crc, FRAM_CRC_SIZE);
FRAMMutex.Unlock();
}
template <typename T, unsigned int OFFSET>
void FRAM<T, OFFSET, 1, 1, 1> :: Bad(const T &t)
{
unsigned short crc;
FRAMMutex.Lock();
FRAMWriteBlock (FRAM_MAC, OFFSET, (uchar*)&t, sizeof(T));
crc = ~CRC16((char*)&t, sizeof(T)); // заведомо ложный CRC
FRAMWriteBlock (FRAM_MAC, OFFSET + sizeof(T), (uchar*)&crc, FRAM_CRC_SIZE);
FRAMMutex.Unlock();
}
///////////////////////////// Одномреный массив ////////////////////////////////
template <typename T, unsigned int OFFSET, unsigned int SIZEX>
class FRAM<T, OFFSET, SIZEX, 1, 1>
{
public:
bool Get (T &t, unsigned int x);
void Set (const T &t, unsigned int x);
void Bad (const T &t, unsigned int x);
};
template <typename T, unsigned int OFFSET, unsigned int SIZEX>
bool FRAM<T, OFFSET, SIZEX, 1, 1> :: Get(T &t, unsigned int x)
{
unsigned short crc;
unsigned int offs;
if(x>=SIZEX) for(;;); // hook
offs = x;
FRAMMutex.Lock();
FRAMReadBlock (FRAM_MAC, OFFSET + offs*(sizeof(T)+FRAM_CRC_SIZE), (uchar*)&t, sizeof(T));
FRAMReadBlock (FRAM_MAC, OFFSET + offs*(sizeof(T)+FRAM_CRC_SIZE)+sizeof(T), (uchar*)&crc, FRAM_CRC_SIZE);
FRAMMutex.Unlock();
return (CRC16((char*)&t, sizeof(T)) == crc);
}
template <typename T, unsigned int OFFSET, unsigned int SIZEX>
void FRAM<T, OFFSET, SIZEX, 1, 1> :: Set(const T &t, unsigned int x)
{
unsigned short crc;
unsigned int offs;
if(x>=SIZEX) for(;;); // hook
offs = x;
FRAMMutex.Lock();
FRAMWriteBlock (FRAM_MAC, OFFSET + offs*(sizeof(T)+FRAM_CRC_SIZE), (uchar*)&t, sizeof(T));
crc = CRC16((char*)&t, sizeof(T));
FRAMWriteBlock (FRAM_MAC, OFFSET + offs*(sizeof(T)+FRAM_CRC_SIZE)+sizeof(T), (uchar*)&crc, FRAM_CRC_SIZE);
FRAMMutex.Unlock();
}
template <typename T, unsigned int OFFSET, unsigned int SIZEX>
void FRAM<T, OFFSET, SIZEX, 1, 1> :: Bad(const T &t, unsigned int x)
{
unsigned short crc;
unsigned int offs;
if(x>=SIZEX) for(;;); // hook
offs = x;
FRAMMutex.Lock();
FRAMWriteBlock (FRAM_MAC, OFFSET + offs*(sizeof(T)+FRAM_CRC_SIZE), (uchar*)&t, sizeof(T));
crc = ~CRC16((char*)&t, sizeof(T)); // заведомо ложный CRC
FRAMWriteBlock (FRAM_MAC, OFFSET + offs*(sizeof(T)+FRAM_CRC_SIZE)+sizeof(T), (uchar*)&crc, FRAM_CRC_SIZE);
FRAMMutex.Unlock();
}
Создаем объект:
Код
...
typedef struct
{
...
}sTimeDate;
...
// сохраненное время (сохраняется периодически чтоб после сбоя можно было восстановить) (несколько копий)
FRAM <sTimeDate, FRAM_RTC_OFFSET, RTC_COPY_AMOUNT> TimeDateNVM;
...
Используем гденито в коде
Код
...
sTimeDate tmp;
...
// Restore time from NVM
// В FRAM хранится несколько копий, при считываении используем первое корректное значение
for(i=0; i<RTC_COPY_AMOUNT; i++)
{
if(TimeDateNVM.Get(tmp, i))
{
if(SetTime(tmp))
{
break;
}
}
}
// время не удалось считать - выставляем флаг
if(i==RTC_COPY_AMOUNT)
{
SetStatusCode(STATUS_RTC_ERROR);
}
Для "больших" контроллеров можно делать более красиво типа так:
http://electronix.ru/forum/index.php?s=&am...st&p=383618http://electronix.ru/forum/index.php?s=&am...st&p=384003Плюс если компилятор поддерживал бы исключения то можно и обработку ошибок культурно реализовать.