302 lines
9.7 KiB
C++
302 lines
9.7 KiB
C++
|
|
/*
|
|||
|
|
* NetX.hh
|
|||
|
|
*
|
|||
|
|
* Created on: 30 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>. 2021 <EFBFBD>.
|
|||
|
|
* 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_ */
|