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

284 lines
6.4 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_ */