MotorControlModuleSDFM_TMS3.../Projects/EFC_Communication/UMLibrary/driver/DataImageStorage.hpp

284 lines
6.6 KiB
C++
Raw Normal View History

2024-06-07 11:12:56 +03:00
/*
* 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_ */