284 lines
6.6 KiB
C++
284 lines
6.6 KiB
C++
/*
|
||
* DataImageStorage.hpp
|
||
*
|
||
* Created on: 16 февр. 2021 г.
|
||
* Author: titov
|
||
*/
|
||
|
||
#ifndef UMLIBRARY_DRIVER_DATAIMAGESTORAGE_HPP_
|
||
#define UMLIBRARY_DRIVER_DATAIMAGESTORAGE_HPP_
|
||
|
||
#include "../systemic/IParameterProvider.hh"
|
||
#include "../systemic/IProcess.hh"
|
||
|
||
#include "../peripheral/IMemoryAccess.hh"
|
||
|
||
#include "IParamStorage.hh"
|
||
|
||
#include <cstddef>
|
||
#include <stdint.h>
|
||
|
||
namespace driver {
|
||
|
||
template<class DataImage>
|
||
class DataImageStorage : public systemic::IProcess, public driver::IParamStorage {
|
||
public:
|
||
typedef DataImage Image;
|
||
|
||
DataImageStorage( peripheral::IMemoryAccess & persistent,
|
||
peripheral::protected_char * buff, std::size_t buff_size );
|
||
void process();
|
||
|
||
systemic::SharedData createParameterBuff( Id parameter_id, std::size_t size );
|
||
systemic::SharedData getParameterBuff( Id parameter_id ) const;
|
||
|
||
//!Данная реализация не поддерживает возможность сохранения отдельных параметров.
|
||
bool flushParameterBuff( Id parameter_id ) { return false; }
|
||
|
||
void flush();
|
||
void load();
|
||
void clear();
|
||
|
||
bool isDataSync() const;
|
||
bool isCrcError() const;
|
||
|
||
virtual ~DataImageStorage() = default;
|
||
|
||
static const std::size_t align = alignof(long double);
|
||
|
||
protected:
|
||
peripheral::IMemoryAccess & memory; //!<Указатель на интерфейс работы с памятью
|
||
|
||
peripheral::protected_char * const buff; //!<Буфер для работы с данными хранимыми в памяти.
|
||
const std::size_t buff_size; //!<Размер буфера.
|
||
|
||
Image image; //!<Образ данных.
|
||
|
||
struct State {
|
||
enum Id {
|
||
Idle,
|
||
UpdateCrc,
|
||
StartWrite,
|
||
WaitWrite,
|
||
StartReadHead,
|
||
WaitReadHead,
|
||
StartReadEnd,
|
||
WaitReadEnd,
|
||
DataImageReset,
|
||
};
|
||
};
|
||
|
||
typename State::Id state;
|
||
|
||
bool crc_error; //!<Ошибка контрольной суммы данных, невозможно восстановить.
|
||
bool data_ready; //!<Структура данных в ОЗУ загружена из ПЗУ.
|
||
bool data_stored; //!<Структура данных в ПЗУ загружена из ОЗУ.
|
||
|
||
bool isMemoryProcessing() const;
|
||
|
||
};
|
||
|
||
}
|
||
|
||
template<class DataImage>
|
||
inline driver::DataImageStorage<DataImage>::DataImageStorage(
|
||
peripheral::IMemoryAccess & persistent, char * buff,
|
||
std::size_t buff_size ) : memory(persistent), buff(buff), buff_size(buff_size), state(State::StartReadHead),
|
||
crc_error(false), data_ready(false), data_stored(true) {}
|
||
|
||
template<class DataImage>
|
||
inline void driver::DataImageStorage<DataImage>::process() {
|
||
|
||
switch(state) {
|
||
case State::UpdateCrc: {
|
||
|
||
if( peripheral::write_lock( buff, buff_size ) ) {
|
||
|
||
image.update_crc();
|
||
|
||
peripheral::write_unlock( buff, buff_size );
|
||
|
||
state = State::StartWrite;
|
||
}
|
||
|
||
} break;
|
||
case State::StartWrite: {
|
||
|
||
if( memory.write( buff, 0, image.get_image_size() ) )
|
||
state = State::WaitWrite;
|
||
|
||
} break;
|
||
case State::WaitWrite: {
|
||
|
||
if( memory.isWriteComplete() )
|
||
state = State::StartReadEnd;
|
||
|
||
} break;
|
||
case State::StartReadHead: {
|
||
|
||
if( memory.read( buff, 0, sizeof(typename Image::Head) ) )
|
||
state = State::WaitReadHead;
|
||
|
||
} break;
|
||
case State::WaitReadHead: {
|
||
|
||
if( memory.isReadComplete() ) {
|
||
|
||
if( image.build_from_buff(buff, buff_size, align) ) {
|
||
|
||
state = State::StartReadEnd;
|
||
|
||
} else {
|
||
|
||
state = State::DataImageReset;
|
||
|
||
}
|
||
}
|
||
|
||
} break;
|
||
case State::StartReadEnd: {
|
||
|
||
if( memory.read( buff + sizeof(typename Image::Head), sizeof(typename Image::Head), image.get_image_size() - sizeof(typename Image::Head) ) )
|
||
state = State::WaitReadEnd;
|
||
|
||
} break;
|
||
case State::WaitReadEnd: {
|
||
|
||
if( memory.isReadComplete() ) {
|
||
|
||
bool crc_equal = image.check_crc();
|
||
|
||
if( crc_equal ) {
|
||
|
||
data_stored = data_ready = true;
|
||
crc_error = false;
|
||
|
||
state = State::Idle;
|
||
|
||
} else {
|
||
|
||
state = State::DataImageReset;
|
||
|
||
}
|
||
}
|
||
|
||
} break;
|
||
case State::DataImageReset: {
|
||
|
||
if( peripheral::write_lock( buff, buff_size ) ) {
|
||
|
||
image.reset();
|
||
|
||
peripheral::write_unlock( buff, buff_size );
|
||
|
||
data_stored = data_ready = false;
|
||
crc_error = true;
|
||
|
||
state = State::Idle;
|
||
}
|
||
|
||
} break;
|
||
case State::Idle: {} break;
|
||
};
|
||
}
|
||
|
||
template<class DataImage>
|
||
systemic::SharedData driver::DataImageStorage<DataImage>::createParameterBuff(
|
||
Id parameter_id, std::size_t size) {
|
||
|
||
if( isMemoryProcessing() )
|
||
return { nullptr, 0 };
|
||
|
||
std::pair<char *, std::size_t> setting = image.show_setting( parameter_id );
|
||
|
||
if( not setting.first or setting.second != size ) {
|
||
|
||
while( not peripheral::write_lock( buff, buff_size ) );
|
||
|
||
{
|
||
data_ready = not image.change_setting_info( parameter_id, size );
|
||
|
||
peripheral::write_unlock( buff, buff_size );
|
||
|
||
return image.show_setting(parameter_id);
|
||
}
|
||
|
||
}
|
||
|
||
return setting;
|
||
|
||
}
|
||
|
||
template<class DataImage>
|
||
systemic::SharedData driver::DataImageStorage<DataImage>::getParameterBuff(
|
||
Id parameter_id ) const {
|
||
|
||
if( isMemoryProcessing() )
|
||
return { nullptr, 0 };
|
||
|
||
return image.show_setting(parameter_id);
|
||
|
||
}
|
||
|
||
template<class DataImage>
|
||
void driver::DataImageStorage<DataImage>::flush() {
|
||
|
||
if( not isMemoryProcessing() ) {
|
||
|
||
data_stored = crc_error = false;
|
||
|
||
state = State::UpdateCrc;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
template<class DataImage>
|
||
void driver::DataImageStorage<DataImage>::load() {
|
||
|
||
if( not isMemoryProcessing() and data_stored ) {
|
||
|
||
data_ready = false;
|
||
|
||
state = State::StartReadHead;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
template<class DataImage>
|
||
void driver::DataImageStorage<DataImage>::clear() {
|
||
|
||
while( not peripheral::write_lock( buff, buff_size ) );
|
||
|
||
image.reset();
|
||
|
||
data_stored = data_ready = false;
|
||
|
||
state = State::Idle;
|
||
|
||
}
|
||
|
||
template<class DataImage>
|
||
bool driver::DataImageStorage<DataImage>::isDataSync() const {
|
||
|
||
return data_ready and data_stored;
|
||
|
||
}
|
||
|
||
template<class DataImage>
|
||
bool driver::DataImageStorage<DataImage>::isCrcError() const {
|
||
|
||
return crc_error;
|
||
|
||
}
|
||
|
||
template<class DataImage>
|
||
bool driver::DataImageStorage<DataImage>::isMemoryProcessing() const {
|
||
|
||
return state != State::Idle;
|
||
|
||
}
|
||
|
||
#endif /* UMLIBRARY_DRIVER_DATAIMAGESTORAGE_HPP_ */
|