302 lines
9.7 KiB
C++
302 lines
9.7 KiB
C++
/*
|
||
* NetX.hh
|
||
*
|
||
* Created on: 30 <20><><EFBFBD><EFBFBD>. 2021 <20>.
|
||
* Author: titov
|
||
*/
|
||
|
||
#ifndef UMLIBRARY_DRIVER_NETX_NETX_HH_
|
||
#define UMLIBRARY_DRIVER_NETX_NETX_HH_
|
||
|
||
#include <utility>
|
||
#include <cstring>
|
||
#include <functional>
|
||
#include <map>
|
||
#include <set>
|
||
#include <vector>
|
||
#include <memory_resource>
|
||
|
||
#include <stdint.h>
|
||
|
||
#include "../../peripheral/ProtectedMemory.hh"
|
||
#include "../../peripheral/IMemoryAccess.hh"
|
||
#include "../../systemic/IProcess.hh"
|
||
#include "../../communication/IMessageServer.hh"
|
||
#include "../../communication/format/BinaryDataPublisher.hh"
|
||
#include "../../communication/format/BinaryDataCollector.hh"
|
||
|
||
#include "lowcifx/HilscherDualPortMemoryMap.hh"
|
||
#include "lowcifx/HilscherPacket.hh"
|
||
|
||
namespace driver {
|
||
namespace netx {
|
||
|
||
class NetX {
|
||
public:
|
||
NetX( std::pair<const char *, std::size_t> name,
|
||
std::pair<peripheral::protected_char *, std::size_t> dpm );
|
||
|
||
static bool isReady( peripheral::protected_char * dpm_origin );
|
||
|
||
bool isReady() const;
|
||
|
||
bool isError() const;
|
||
|
||
void reset();
|
||
|
||
class CommunicationChannel {
|
||
public:
|
||
enum ChannelId {
|
||
CH0, CH1, CH2, CH3
|
||
};
|
||
|
||
typedef uint32_t ErrorCode;
|
||
|
||
struct Info {
|
||
uint16_t id; //!<
|
||
uint16_t type; //!<DOC060302DPM17EN, page 84. Table 60: System Channel: Communication Class
|
||
uint16_t protocol; //!<DOC060302DPM17EN, page 85-86. Table 61: System Channel: Protocol Class
|
||
uint16_t conformance; //!<DOC060302DPM17EN, page 86.
|
||
};
|
||
|
||
struct Mailbox : public systemic::IProcess,
|
||
public communication::IMessageRouter {};
|
||
|
||
CommunicationChannel( std::pmr::memory_resource * description, std::pmr::memory_resource * buffer );
|
||
|
||
peripheral::IMemoryAccess & cyclic();
|
||
|
||
communication::IBinaryDataReadEvent & cyclic_read();
|
||
communication::IBinaryDataWriteEvent & cyclic_write();
|
||
|
||
Mailbox & mailbox();
|
||
|
||
bool isError() const;
|
||
bool isRunning() const;
|
||
bool isCommunicating() const;
|
||
bool isProtocolRegistred() const;
|
||
|
||
ErrorCode getErrorCode() const;
|
||
float getErrorCounter() const;
|
||
float getWatchdogCounter() const; //!<
|
||
|
||
void start();
|
||
void stop();
|
||
void watchdog(); //!<
|
||
|
||
Info info() const;
|
||
|
||
private:
|
||
struct HandshakeData : public peripheral::IMemoryAccess,
|
||
communication::IBinaryDataReadEvent, communication::IBinaryDataWriteEvent {
|
||
bool ready_to_be_read(); //!<
|
||
bool view( char * data, std::size_t begin, std::size_t size ); //!<
|
||
bool accept(); //!<
|
||
|
||
bool ready_to_be_written(); //!<
|
||
bool set( const char * data, std::size_t begin, std::size_t size ); //!<
|
||
bool commit(); //!<
|
||
|
||
//!<21><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||
void read_event( communication::IBinaryDataSubscriber & subscriber );
|
||
|
||
//!<21><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||
void write_event( communication::IBinaryDataIssuer & issuer );
|
||
|
||
bool read( char * data, std::size_t begin, std::size_t size );
|
||
bool write( const char * data, std::size_t begin, std::size_t size );
|
||
|
||
bool isReadComplete() const;
|
||
bool isWriteComplete() const;
|
||
std::size_t getCapacity() const;
|
||
|
||
peripheral::protected_char * input = nullptr;
|
||
peripheral::protected_char * output = nullptr;
|
||
peripheral::protected_char * handshake = nullptr;
|
||
std::size_t capacity = 0;
|
||
|
||
bool read_complete = false;
|
||
bool write_request = false;
|
||
|
||
const uint16_t read_mask;
|
||
const uint16_t write_mask;
|
||
|
||
HandshakeData( uint16_t read_mask, uint16_t write_mask );
|
||
};
|
||
|
||
HandshakeData pd0_data;
|
||
HandshakeData pd1_data;
|
||
HandshakeData mb_rec_data;
|
||
HandshakeData mb_tx_data;
|
||
|
||
class MailboxHandler : public Mailbox {
|
||
|
||
typedef std::map<ServerId, communication::IMessageServer *, std::greater<ServerId>,
|
||
std::pmr::polymorphic_allocator<
|
||
std::pair<const ServerId, communication::IMessageServer *> > >
|
||
Servers;
|
||
|
||
HandshakeData & receive;
|
||
HandshakeData & transmit;
|
||
|
||
Servers servers;
|
||
|
||
enum State {
|
||
RequestRegisterApplication,
|
||
WaitRegisterApplication,
|
||
ConfirmationRegisterApplication,
|
||
AcceptRegisterApplication,
|
||
WaitReceive,
|
||
ReadHeader,
|
||
ReadData,
|
||
AcceptReceive,
|
||
RequestServer,
|
||
WaitSend,
|
||
WriteHeader,
|
||
WriteData,
|
||
AcceptSend,
|
||
Stop,
|
||
} state;
|
||
|
||
bool application_registred;
|
||
|
||
struct Packet {
|
||
packet::HIL_PACKET_HEADER header;
|
||
std::vector< char, std::pmr::polymorphic_allocator<char> > data;
|
||
|
||
Packet( std::pmr::memory_resource * buffer );
|
||
} request, response;
|
||
|
||
struct Client : public communication::IMessageClient {
|
||
|
||
Client( std::vector< char, std::pmr::polymorphic_allocator<char> > & data );
|
||
|
||
std::vector< char, std::pmr::polymorphic_allocator<char> > & data;
|
||
|
||
bool response( const char * data, std::size_t size );
|
||
|
||
bool flag = false;
|
||
};
|
||
|
||
public:
|
||
MailboxHandler( HandshakeData & receive, HandshakeData & transmit,
|
||
std::pmr::memory_resource * description, std::pmr::memory_resource * buffer );
|
||
|
||
void attach(communication::IMessageServer * server, ServerId id );
|
||
void start();
|
||
bool stop();
|
||
|
||
void process();
|
||
|
||
const bool & enable() const;
|
||
|
||
} mailbox_handler;
|
||
|
||
friend NetX;
|
||
|
||
peripheral::protected_char * handshake;
|
||
peripheral::protected_char * channel;
|
||
|
||
bool board_ready_status;
|
||
mutable std::pair< uint32_t, bool> cos_cache;
|
||
|
||
Info self_info;
|
||
|
||
void setBoardReadyStatus( bool ready_status );
|
||
|
||
void updateAppCos( uint32_t set, uint32_t clear = 0 );
|
||
uint32_t readNetXCos() const;
|
||
};
|
||
|
||
CommunicationChannel * open( CommunicationChannel::ChannelId id,
|
||
std::pmr::memory_resource * allocator,
|
||
std::pmr::memory_resource * description, std::pmr::memory_resource * buffer );
|
||
|
||
private:
|
||
typedef uint32_t ErrorCode;
|
||
typedef uint32_t ServerId;
|
||
|
||
static const std::size_t NETX_COMM_CHANNELS_NUM = 4;
|
||
static const std::size_t NETX_APP_CHANNELS_NUM = 2;
|
||
static const uint32_t NETX_DPM_COOKIE = 0x5874656E;
|
||
|
||
struct DpmLayout {
|
||
struct {
|
||
std::pair<peripheral::protected_char *, std::size_t> channel;
|
||
std::pair<peripheral::protected_char *, std::size_t> handshake;
|
||
std::pair<peripheral::protected_char *, std::size_t> mailbox_send;
|
||
std::pair<peripheral::protected_char *, std::size_t> mailbox_receive;
|
||
} system;
|
||
struct {
|
||
std::pair<peripheral::protected_char *, std::size_t> channel;
|
||
} handshake;
|
||
struct {
|
||
std::pair<peripheral::protected_char *, std::size_t> channel;
|
||
std::pair<peripheral::protected_char *, std::size_t> handshake;
|
||
std::pair<peripheral::protected_char *, std::size_t> cyclic_in;
|
||
std::pair<peripheral::protected_char *, std::size_t> cyclic_out;
|
||
std::pair<peripheral::protected_char *, std::size_t> mailbox_send;
|
||
std::pair<peripheral::protected_char *, std::size_t> mailbox_receive;
|
||
uint16_t type;
|
||
uint16_t protocol;
|
||
uint16_t conformance;
|
||
} communications[NETX_COMM_CHANNELS_NUM];
|
||
struct {
|
||
std::pair<peripheral::protected_char *, std::size_t> channel;
|
||
std::pair<peripheral::protected_char *, std::size_t> handshake;
|
||
} applications[NETX_APP_CHANNELS_NUM];
|
||
} layout;
|
||
|
||
struct Dpm {
|
||
peripheral::protected_char * base;
|
||
std::size_t size;
|
||
} dpm;
|
||
|
||
struct Info {
|
||
uint16_t dip_address; //!<
|
||
uint16_t device_class; //!<
|
||
uint32_t device_number; //!<
|
||
uint32_t serial_number; //!<
|
||
} device_info;
|
||
|
||
struct Channel {
|
||
enum Id {
|
||
System,
|
||
Handshake,
|
||
CommunicationAlfa,
|
||
CommunicationBeta,
|
||
CommunicationGamma,
|
||
CommunicationDelta,
|
||
ApplicationZero,
|
||
ApplicationOne
|
||
};
|
||
|
||
static const std::size_t num_channels = 8;
|
||
|
||
static peripheral::protected_char * handshake( peripheral::protected_char * base, Id id );
|
||
static peripheral::protected_char * status( peripheral::protected_char * base, Id id );
|
||
};
|
||
|
||
mutable bool ready_status;
|
||
|
||
CommunicationChannel * communication_channels[NETX_COMM_CHANNELS_NUM];
|
||
mutable ErrorCode errors[Channel::num_channels];
|
||
|
||
void resetSystem();
|
||
|
||
static bool checkDpmCookie( peripheral::protected_char * dpm_origin );
|
||
bool hasDefaultDpmLayout() const;
|
||
|
||
bool isChannelReady( Channel::Id channel ) const;
|
||
bool isChannelRunning( Channel::Id channel ) const;
|
||
bool isChannelCommunicating( Channel::Id channel ) const;
|
||
void notifyChannels( bool new_ready_status ) const;
|
||
|
||
std::pair<bool, uint32_t> checkChannelError( Channel::Id channel ) const;
|
||
};
|
||
|
||
} /* namespace netx */
|
||
} /* namespace driver */
|
||
|
||
#endif /* UMLIBRARY_DRIVER_NETX_NETX_HH_ */
|