MotorControlModuleSDFM_TMS3.../Projects/EFC_Communication/UMLibrary/driver/DataImageStorage.hpp
2024-06-07 11:12:56 +03:00

284 lines
6.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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_ */