1
0
forked from fsfw/fsfw

Adding Code for Linux

This commit is contained in:
2018-07-13 18:28:26 +02:00
parent db1f93a155
commit fd782b20c0
90 changed files with 2411 additions and 1497 deletions

View File

@ -5,7 +5,7 @@
#include <stddef.h>
ReturnValue_t RMAP::reset(RMAPCookie* cookie) {
return cookie->channel->reset();
return cookie->getChannel()->reset();
}
RMAP::RMAP(){
@ -22,7 +22,7 @@ ReturnValue_t RMAP::sendWriteCommand(RMAPCookie *cookie, uint8_t* buffer,
if (cookie->getChannel() == NULL) {
return COMMAND_NO_CHANNEL;
}
instruction = RMAP_COMMAND_WRITE | cookie->command_mask;
instruction = RMAPIds::RMAP_COMMAND_WRITE | cookie->getCommandMask();
return cookie->getChannel()->sendCommand(cookie, instruction, buffer,
length);
@ -32,7 +32,7 @@ ReturnValue_t RMAP::getWriteReply(RMAPCookie *cookie) {
if (cookie->getChannel() == NULL) {
return COMMAND_NO_CHANNEL;
}
if (cookie->header.instruction & (1 << RMAP_COMMAND_BIT_WRITE)) {
if (cookie->getHeader()->instruction & (1 << RMAPIds::RMAP_COMMAND_BIT_WRITE)) {
return cookie->getChannel()->getReply(cookie, NULL, NULL);
} else {
return REPLY_MISSMATCH;
@ -53,8 +53,8 @@ ReturnValue_t RMAP::sendReadCommand(RMAPCookie *cookie, uint32_t expLength) {
if (cookie->getChannel() == NULL) {
return COMMAND_NO_CHANNEL;
}
command = RMAP_COMMAND_READ
| (cookie->command_mask & ~(1 << RMAP_COMMAND_BIT_VERIFY));
command = RMAPIds::RMAP_COMMAND_READ
| (cookie->getCommandMask() & ~(1 << RMAPIds::RMAP_COMMAND_BIT_VERIFY));
return cookie->getChannel()->sendCommand(cookie, command, NULL, expLength);
@ -68,7 +68,7 @@ ReturnValue_t RMAP::getReadReply(RMAPCookie *cookie, uint8_t **buffer,
if (buffer == NULL || size == NULL) {
return DeviceCommunicationIF::NULLPOINTER;
}
if (cookie->header.instruction & (1 << RMAP_COMMAND_BIT_WRITE)) {
if (cookie->getHeader()->instruction & (1 << RMAPIds::RMAP_COMMAND_BIT_WRITE)) {
return REPLY_MISSMATCH;
} else {
return cookie->getChannel()->getReply(cookie, buffer, size);

View File

@ -1,11 +1,12 @@
#ifndef RMAPCHANNELIF_H_
#define RMAPCHANNELIF_H_
#include <framework/rmap/RMAP.h>
#include <framework/tasks/PeriodicTaskIF.h>
#include <framework/rmap/RMAPCookie.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
class RMAPChannelIF: public RMAP {
class RMAPChannelIF {
public:
virtual ~RMAPChannelIF(){};
/**
* Reset an RMAP channel
*
@ -42,7 +43,7 @@ public:
* - @c COMMAND_PORT_OUT_OF_RANGE if the port is invalid
*/
virtual ReturnValue_t setPort(int8_t port, uint8_t dest_addr,
uint8_t src_addr, PeriodicTaskIF* currentTask)=0;
uint8_t src_addr)=0;
/**
* Assign a SpaceWire port to the Channel
@ -54,7 +55,7 @@ public:
* - @c COMMAND_OK if port was changed
* - @c COMMAND_PORT_OUT_OF_RANGE if the port is invalid
*/
virtual ReturnValue_t setPort(int8_t port, PeriodicTaskIF* currentTask)=0;
virtual ReturnValue_t setPort(int8_t port)=0;
/**
* Send an RMAP command

View File

@ -20,13 +20,11 @@ RMAPCookie::RMAPCookie() {
this->header.datalen_m = 0;
this->header.datalen_l = 0;
this->header.header_crc = 0;
this->txdesc = NULL;
this->rxdesc_index = 0;
this->channel = NULL;
this->command_mask = 0;
this->dataCRC = 0;
this->maxReplyLen = 0;
}
@ -47,11 +45,9 @@ RMAPCookie::RMAPCookie(uint32_t set_address, uint8_t set_extended_address,
this->header.datalen_m = 0;
this->header.datalen_l = 0;
this->header.header_crc = 0;
this->txdesc = NULL;
this->rxdesc_index = 0;
this->channel = set_channel;
this->command_mask = set_command_mask;
this->dataCRC = 0;
this->maxReplyLen = maxReplyLen;
}
@ -104,3 +100,25 @@ uint32_t RMAPCookie::getMaxReplyLen() const {
void RMAPCookie::setMaxReplyLen(uint32_t maxReplyLen) {
this->maxReplyLen = maxReplyLen;
}
RMAPStructs::rmap_cmd_header* RMAPCookie::getHeader(){
return &this->header;
}
uint16_t RMAPCookie::getTransactionIdentifier() const {
return static_cast<uint16_t>((header.tid_h << 8) | (header.tid_l));
}
void RMAPCookie::setTransactionIdentifier(uint16_t id_) {
header.tid_l = id_ & 0xFF;
header.tid_h = (id_ >> 8 ) & 0xFF;
}
uint32_t RMAPCookie::getDataLength() const {
return static_cast<uint32_t>(header.datalen_h << 16 | header.datalen_m << 8 | header.datalen_l);
}
void RMAPCookie::setDataLength(uint32_t length_) {
header.datalen_l = length_ & 0xff;
header.datalen_m = (length_ >> 8) & 0xff;
header.datalen_h = (length_ >> 16) & 0xff;
}

View File

@ -7,8 +7,6 @@
class RMAPChannelIF;
class RMAPCookie : public Cookie{
friend class RMAP;
friend class RmapSPWChannel;
public:
//To Uli: Sorry, I need an empty ctor to initialize an array of cookies.
RMAPCookie();
@ -20,24 +18,41 @@ public:
void setAddress(uint32_t address);
uint32_t getAddress();
void setExtendedAddress(uint8_t);
uint8_t getExtendedAddress();
void setChannel(RMAPChannelIF *channel);
RMAPChannelIF *getChannel();
void setCommandMask(uint8_t commandMask);
uint8_t getCommandMask();
uint32_t getMaxReplyLen() const;
void setMaxReplyLen(uint32_t maxReplyLen);
//rmap_cookie* getDeviceDescriptor();
uint16_t getTransactionIdentifier() const;
void setTransactionIdentifier(uint16_t id_);
RMAPStructs::rmap_cmd_header* getHeader();
uint32_t getDataLength() const;
void setDataLength(uint32_t lenght_);
uint8_t getDataCrc() const {
return dataCRC;
}
void setDataCrc(uint8_t dataCrc) {
dataCRC = dataCrc;
}
protected:
RMAPStructs::rmap_cmd_header header;
void *txdesc;
uint8_t rxdesc_index;
RMAPChannelIF *channel;
uint8_t command_mask;
uint32_t maxReplyLen;
uint8_t dataCRC;
};
#endif /* RMAPCOOKIE_H_ */

View File

@ -0,0 +1,47 @@
#include <framework/rmap/RmapDeviceCommunicationIF.h>
#include <framework/rmap/RMAP.h>
//TODO Cast here are all potential bugs
RmapDeviceCommunicationIF::~RmapDeviceCommunicationIF() {
}
ReturnValue_t RmapDeviceCommunicationIF::sendMessage(Cookie* cookie,
uint8_t* data, uint32_t len) {
return RMAP::sendWriteCommand((RMAPCookie *) cookie, data, len);
}
ReturnValue_t RmapDeviceCommunicationIF::getSendSuccess(Cookie* cookie) {
return RMAP::getWriteReply((RMAPCookie *) cookie);
}
ReturnValue_t RmapDeviceCommunicationIF::requestReceiveMessage(
Cookie* cookie) {
return RMAP::sendReadCommand((RMAPCookie *) cookie,
((RMAPCookie *) cookie)->getMaxReplyLen());
}
ReturnValue_t RmapDeviceCommunicationIF::readReceivedMessage(Cookie* cookie,
uint8_t** buffer, uint32_t* size) {
return RMAP::getReadReply((RMAPCookie *) cookie, buffer, size);
}
ReturnValue_t RmapDeviceCommunicationIF::setAddress(Cookie* cookie,
uint32_t address) {
((RMAPCookie *) cookie)->setAddress(address);
return HasReturnvaluesIF::RETURN_OK;
}
uint32_t RmapDeviceCommunicationIF::getAddress(Cookie* cookie) {
return ((RMAPCookie *) cookie)->getAddress();
}
ReturnValue_t RmapDeviceCommunicationIF::setParameter(Cookie* cookie,
uint32_t parameter) {
//TODO Empty?
return HasReturnvaluesIF::RETURN_FAILED;
}
uint32_t RmapDeviceCommunicationIF::getParameter(Cookie* cookie) {
return 0;
}

View File

@ -0,0 +1,80 @@
#ifndef MISSION_RMAP_RMAPDEVICECOMMUNICATIONINTERFACE_H_
#define MISSION_RMAP_RMAPDEVICECOMMUNICATIONINTERFACE_H_
#include <framework/devicehandlers/DeviceCommunicationIF.h>
/**
* @brief This class is a implementation of a DeviceCommunicationIF for RMAP calls. It expects RMAPCookies or a derived class of RMAPCookies
*
* @details The open, close and reOpen calls are mission specific
* The open call might return any child of RMAPCookies
*
* \ingroup rmap
*/
class RmapDeviceCommunicationIF: public DeviceCommunicationIF {
public:
virtual ~RmapDeviceCommunicationIF();
/**
* This method is mission specific as the open call will return a mission specific cookie
*
* @param cookie A cookie, can be mission specific subclass of RMAP Cookie
* @param address The address of the RMAP Cookie
* @param maxReplyLen Maximum length of expected reply
* @return
*/
virtual ReturnValue_t open(Cookie **cookie, uint32_t address,
uint32_t maxReplyLen) = 0;
/**
* Use an existing cookie to open a connection to a new DeviceCommunication.
* The previous connection must not be closed.
* If the returnvalue is not RETURN_OK, the cookie is unchanged and
* can be used with the previous connection.
*
* @param cookie
* @param address
* @param maxReplyLen
* @return
*/
virtual ReturnValue_t reOpen(Cookie *cookie, uint32_t address,
uint32_t maxReplyLen) = 0;
/**
* Closing call of connection and memory free of cookie. Mission dependent call
* @param cookie
*/
virtual void close(Cookie *cookie) = 0;
//SHOULDDO can data be const?
/**
*
*
* @param cookie Expects an RMAPCookie or derived from RMAPCookie Class
* @param data Data to be send
* @param len Length of the data to be send
* @return - Return codes of RMAP::sendWriteCommand()
*/
virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data,
uint32_t len);
virtual ReturnValue_t getSendSuccess(Cookie *cookie);
virtual ReturnValue_t requestReceiveMessage(Cookie *cookie);
virtual ReturnValue_t readReceivedMessage(Cookie *cookie, uint8_t **buffer,
uint32_t *size);
virtual ReturnValue_t setAddress(Cookie *cookie, uint32_t address);
virtual uint32_t getAddress(Cookie *cookie);
virtual ReturnValue_t setParameter(Cookie *cookie, uint32_t parameter);
virtual uint32_t getParameter(Cookie *cookie);
};
#endif /* MISSION_RMAP_RMAPDEVICECOMMUNICATIONINTERFACE_H_ */

View File

@ -1,744 +0,0 @@
#include <framework/rmap/RmapSPWChannel.h>
extern "C" {
#include <bsp_flp/hw_timer/hw_timer.h>
#include <bsp_flp/crc/crc.h>
}
#include <framework/datapool/DataSet.h>
#include <framework/datapool/PoolVariable.h>
//////////////////////////////////////////////////////////////////////////////////
//bits for the failure table
#define RMAP_RX_FAIL_CHECKED 0
#define RMAP_RX_FAIL_EEP 1
#define RMAP_RX_FAIL_TRUNC 2
#define RMAP_RX_FAIL_LEN 3
#define RMAP_RX_FAIL_CRC 4
#define RMAP_RX_FAIL_DST_ADDR 5
#define RMAP_RX_FAIL_PROTO 6
#define RMAP_RX_FAIL_INSTR_TYPE 7 //this is when the instruction byte is really wrong (must be caused by device)
#define RMAP_RX_FAIL_INSTR 8 //this is when a wrong instruction byte was caused by a wrong instruction sent by the host and detected by the device
#define RMAP_RX_FAIL_SRC_ADDR 9
#define RMAP_RX_FAIL_LEN_MISSMATCH 10
#define RMAP_RX_FAIL_WRONG_REPLY 11 //a read command was answered by a write reply or the other way round
//pad a number so it is word aligned (32bit)
#define BYTES2WORDS(number) (((number) +3)/4)
RmapSPWChannel::RmapSPWChannel(object_id_t setObjectId,
uint16_t buffersize_words, uint32_t maxPacketSize, int8_t portNr,
uint8_t dest_addr, uint8_t src_addr, PeriodicTaskIF* currentTask,
datapool::opus_variable_id portVariable) :
SystemObject(setObjectId), port(NULL), rx_index(0), max_rx(128), tx_index(
0), max_tx(64), src_addr(src_addr), dest_addr(dest_addr), portPoolId(
portVariable) {
buffer = new uint32_t[buffersize_words];
buffer_pointer = buffer;
end_of_buffer = &buffer[buffersize_words];
max_packet_len = maxPacketSize & 0x1FFFFFC;
tid = 0;
failure_table = new uint16_t[128];
setPort(portNr, dest_addr, src_addr, currentTask);
}
RmapSPWChannel::~RmapSPWChannel() {
delete[] buffer;
delete[] failure_table;
}
ReturnValue_t RmapSPWChannel::reset() {
uint8_t link_down = 0;
uint8_t missed, i;
uint32_t state;
//check if channel has a port
if (port == NULL) {
return COMMAND_CHANNEL_DEACTIVATED;
}
//check state of SPW
state = spw_get_state(port);
if (state != SPW_STATE_RUN) {
triggerEvent(SPW_LINK_DOWN, getCurrentPortNr());
link_down++;
}
//SPW link errors
if ((state = (port->SPWSTR & 0x1de)) != 0) {
reportSpwstr(state);
}
//check DMA errors
if ((state = (port->SPWCHN & 0x180)) != 0) {
triggerEvent(SPW_ERROR, SPW_DMA, state);
}
//hard reset spw
//only safe way to reset the descriptors
spw_reset(port);
spw_reset_rxdesc_table(port);
spw_reset_txdesc_table(port);
//reset internal buffer
buffer_pointer = buffer;
#ifdef LEON
asm("flush");
#endif
//check how many packets were received
missed = 0;
if ((rx_index != 0)
&& (rx_descriptor_table[rx_index - 1].word0
& (1 << SPW_DESC_RX_ENABLE))) {
// printf("word 0 = %08lx\n",
// rx_descriptor_table[rx_index - 1].word0);
for (missed = 1; missed < rx_index; missed++) {
if (!(rx_descriptor_table[rx_index - 1 - missed].word0
& (1 << SPW_DESC_RX_ENABLE)))
break;
}
triggerEvent(RMAP_MISSED_REPLIES, missed);
//missed is number of missed replies
}
if (missed == rx_index) {
link_down++;
}
for (i = rx_index - missed; i > 0; i--) {
if (!(failure_table[i - 1] & 1)) {
checkRxDescPacket(&(rx_descriptor_table[i - 1]),
&(failure_table[i - 1]));
}
if (failure_table[i - 1] & 0xFFFE) {
reportFailures(failure_table[i - 1], i - 1);
}
}
//reset descriptor counter
rx_index = 0;
tx_index = 0;
//clear all descriptors to get rid of unused ones
spw_rx_desc *rx_desc;
i = 0;
for (rx_desc = rx_descriptor_table; rx_desc < &rx_descriptor_table[max_rx];
rx_desc++) {
rx_desc->word0 = 0;
failure_table[i++] = 0;
}
spw_tx_desc *tx_desc;
for (tx_desc = tx_descriptor_table; tx_desc < &tx_descriptor_table[max_tx];
tx_desc++) {
tx_desc->word0 = 0;
}
//restart spw
spw_start(port);
if (link_down > 1) {
return LINK_DOWN;
}
return RETURN_OK;
}
ReturnValue_t RmapSPWChannel::isActive() {
if (port == NULL) {
return COMMAND_CHANNEL_DEACTIVATED;
}
uint32_t state = spw_get_state(port);
if (state != SPW_STATE_RUN) {
return LINK_DOWN;
}
return RETURN_OK;
}
ReturnValue_t RmapSPWChannel::setPort(int8_t portNr, uint8_t dest_addr,
uint8_t src_addr, PeriodicTaskIF* currentTask) {
SPW_dev *new_port;
//only accept ports from a list or -1, which disables channel
if (portNr >= SPW_devices.len && portNr < -1) {
return COMMAND_PORT_OUT_OF_RANGE;
}
//check if crc is enabled
if (portNr != -1) {
new_port = SPW_devices.devices[portNr];
if (!spw_crc_enabled(new_port)) {
return NO_HW_CRC;
}
} else {
new_port = NULL;
}
//anounce change
triggerEvent(RMAP_SWITCHED_PORT, portNr, getCurrentPortNr());
if (portPoolId != 0) {
DataSet mySet;
PoolVariable<int8_t> channel(portPoolId, &mySet,
PoolVariableIF::VAR_WRITE);
mySet.read();
channel = portNr;
mySet.commit(PoolVariableIF::VALID);
}
//reset the old port to clear pending errors etc
reset();
//assign new port
this->port = new_port;
if (new_port == NULL) {
return RETURN_OK;
}
//stop the new port
spw_stop(new_port);
//make sure the new port has the max len set
new_port->SPWRXL = max_packet_len;
//set the addresses
this->dest_addr = dest_addr;
this->src_addr = src_addr;
new_port->SPWNDR = src_addr;
//set descriptor table
tx_descriptor_table = spw_get_tx_descriptor_table(new_port);
rx_descriptor_table = spw_get_rx_descriptor_table(new_port);
spw_reset_rxdesc_table(new_port);
spw_reset_txdesc_table(new_port);
//reset the channel
spw_start(new_port);
currentTask->sleepFor(10);
reset();
return RETURN_OK;
}
ReturnValue_t RmapSPWChannel::setPort(int8_t port, PeriodicTaskIF* currentTask) {
return setPort(port, this->dest_addr, this->src_addr, currentTask);
}
spw_rx_desc* RmapSPWChannel::findReply(RMAPCookie* cookie) {
spw_rx_desc *rxdesc;
uint8_t i;
//look downwards
for (i = cookie->rxdesc_index; i < 200; i--) {
if ((rxdesc = checkRxDesc(cookie, i)) != NULL) {
return rxdesc;
}
}
//look upwards
for (i = cookie->rxdesc_index + 1; i < max_rx; i++) {
if ((rxdesc = checkRxDesc(cookie, i)) != NULL) {
return rxdesc;
}
}
return NULL;
}
ReturnValue_t RmapSPWChannel::sendCommand(RMAPCookie* cookie,
uint8_t instruction, uint8_t* data, uint32_t datalen) {
uint8_t headerlen = RMAP_COMMAND_HEADER_LEN - 1;
//check if channel has a port
if (port == NULL) {
return COMMAND_CHANNEL_DEACTIVATED;
}
//max send limit
if ((instruction & (1 << RMAP_COMMAND_BIT_WRITE))
&& (datalen & ~0xFFFFFF)) {
printf("application wants to send to much data with cookie at %p\n",
cookie);
return TOO_MUCH_DATA;
}
//max receive limit
if ((!(instruction & (1 << RMAP_COMMAND_BIT_WRITE)))
&& (datalen + 1 + RMAP_READ_REPLY_HEADER_LEN > max_packet_len)) {
printf("application wants to read too much data with cookie at %p\n",
cookie);
return TOO_MUCH_DATA;
}
//check if enough space is left in the buffer
//must be checked against max_packet_len, as you can not tell what hw will do,
//except that it will write this number at most
if ((buffer_pointer + BYTES2WORDS(max_packet_len))
> end_of_buffer) {
printf("buffer is full, cookie is %p\n", cookie);
return COMMAND_BUFFER_FULL;
}
//we allow tx descriptor wrap at user discretion, but check we have rx descriptors available
//as we dont wrap them
//note: [tr]x_index will be incremented when done
if (rx_index >= max_rx) {
triggerEvent(RMAP_NO_RX_DESCRIPTORS, 0);
return COMMAND_NO_DESCRIPTORS_AVAILABLE;
}
if (tx_index >= max_tx) {
if (max_tx == 64) {
tx_index = 0;
} else {
triggerEvent(RMAP_NO_TX_DESCRIPTORS, 0);
return COMMAND_NO_DESCRIPTORS_AVAILABLE;
}
}
//check if tx descriptor is activated, which means we wrapped the table
//and came to a descriptor not yet sent
#ifdef LEON
asm("flush");
#endif
if (tx_descriptor_table[tx_index].word0 & (1 << SPW_DESC_TX_ENABLE)) {
return COMMAND_NO_DESCRIPTORS_AVAILABLE;
}
//prepare header
//set addresses
cookie->header.source_address = src_addr;
cookie->header.dest_address = dest_addr;
//set instruction
cookie->header.instruction = instruction;
//set the tid
cookie->header.tid_l = tid & 0xff;
cookie->header.tid_h = (tid >> 8) & 0xff;
tid++;
//set datalen
cookie->header.datalen_l = datalen & 0xff;
cookie->header.datalen_m = (datalen >> 8) & 0xff;
cookie->header.datalen_h = (datalen >> 16) & 0xff;
//configure rx_descriptor
rx_descriptor_table[rx_index].word1 = (uint32_t) buffer_pointer;
rx_descriptor_table[rx_index].word0 = (1 << SPW_DESC_RX_ENABLE);
//inc buffer
if (instruction & (1 << RMAP_COMMAND_BIT_WRITE)) {
buffer_pointer += BYTES2WORDS(RMAP_WRITE_REPLY_HEADER_LEN);
} else {
buffer_pointer += BYTES2WORDS(RMAP_READ_REPLY_HEADER_LEN + datalen + 1); //+1 for crc
}
//configure tx_descriptor
tx_descriptor_table[tx_index].word1 = (uint32_t) &cookie->header;
if (instruction & (1 << RMAP_COMMAND_BIT_WRITE)) {
tx_descriptor_table[tx_index].word2 = datalen & 0xFFFFFF;
} else {
tx_descriptor_table[tx_index].word2 = 0;
}
tx_descriptor_table[tx_index].word3 = (uint32_t) data;
if (instruction & (1 << RMAP_COMMAND_BIT_WRITE)) {
tx_descriptor_table[tx_index].word0 = headerlen
| (1 << SPW_DESC_TX_ENABLE) | (1 << SPW_DESC_TX_CRC_DATA)
| (1 << SPW_DESC_TX_CRC_HEADER);
} else {
tx_descriptor_table[tx_index].word0 = headerlen
| (1 << SPW_DESC_TX_ENABLE) | (1 << SPW_DESC_TX_CRC_HEADER);
}
//remember descriptors to find them faster when looking for the reply
cookie->txdesc = &(tx_descriptor_table[tx_index]);
cookie->rxdesc_index = rx_index;
tx_index++;
rx_index++;
//inform the hw about the new descriptors
spw_new_rxdesc(port);
spw_new_txdesc(port);
return RETURN_OK;
}
ReturnValue_t RmapSPWChannel::getReply(RMAPCookie* cookie, uint8_t** databuffer,
uint32_t* len) {
spw_rx_desc *rxdesc;
ReturnValue_t result;
uint32_t packetlen;
//was the command sent right
result = checkTxDesc(cookie);
if (result != RETURN_OK) {
return result;
}
//command was sent
//find the rx descriptor
if ((rxdesc = findReply(cookie)) == NULL) {
return REPLY_NO_REPLY;
}
//reply_header = (rmap_write_reply_header *) rxdesc->word1;
if (databuffer != NULL) {
packetlen = (rxdesc->word0 & 0x1FFFFFF);
*databuffer = ((uint8_t *) rxdesc->word1) + RMAP_READ_REPLY_HEADER_LEN;
*len = packetlen - RMAP_READ_REPLY_HEADER_LEN - 1;
}
result = ((RMAPStructs::rmap_write_reply_header *) (rxdesc->word1))->status;
//result is an RMAP standard return code, not a ReturnValue_t, thus we check against 0
//and do MAKE_RETURN_CODE(), or set to RETURN_OK respectively
//if RETURN_OK == 0, this is not neccessary, but we should not make assumptions on the
//value of ReturnValues
if (result != 0) {
result = ((RMAP::INTERFACE_ID << 8) + (result));
} else {
result = RETURN_OK;
}
return result;
}
ReturnValue_t RmapSPWChannel::checkTxDesc(RMAPCookie* cookie) {
RMAPStructs::rmap_cmd_header *header_desc;
uint16_t tid_desc, tid_cookie;
uint32_t status;
#ifdef LEON
asm("flush");
#endif
if (cookie->txdesc == NULL) {
return REPLY_NOT_SENT;
}
header_desc =
(RMAPStructs::rmap_cmd_header *) ((spw_tx_desc *) cookie->txdesc)->word1;
status = ((spw_tx_desc *) cookie->txdesc)->word0
& ((1 << SPW_DESC_TX_ENABLE) | (1 << SPW_DESC_TX_LINK_ERROR));
tid_cookie = (cookie->header.tid_l) | (cookie->header.tid_h << 8);
tid_desc = (header_desc->tid_l) | (header_desc->tid_h << 8);
if (tid_cookie != tid_desc) {
//tx descriptor was reused, we have no info so let's assume the best
return RETURN_OK;
}
//was command sent or an error seen?
if (status == (1 << SPW_DESC_TX_ENABLE)) {
return REPLY_NOT_YET_SENT;
}
if (status & (1 << SPW_DESC_TX_LINK_ERROR)) {
triggerEvent(SPW_ERROR, SPW_LINK_ERROR, 0);
return REPLY_NOT_SENT;
}
return RETURN_OK;
}
spw_rx_desc* RmapSPWChannel::checkRxDesc(RMAPCookie* cookie,
uint8_t rxdesc_index) {
uint16_t *failureEntry, tid_desc, tid_cookie;
spw_rx_desc *rxdesc;
RMAPStructs::rmap_read_reply_header *reply_header;
rxdesc = &rx_descriptor_table[rxdesc_index];
failureEntry = &failure_table[rxdesc_index];
if (!(*failureEntry)) {
checkRxDescPacket(rxdesc, failureEntry);
}
if (*failureEntry != 1 << RMAP_RX_FAIL_CHECKED) {
return NULL;
}
//the packet has been checked and is formally correct
//only thing left is to check tid and instruction:
reply_header = (RMAPStructs::rmap_read_reply_header *) rxdesc->word1;
tid_cookie = cookie->header.tid_l | (cookie->header.tid_h << 8);
tid_desc = reply_header->tid_l | (reply_header->tid_h << 8);
if (tid_desc != tid_cookie) {
return NULL;
}
if ((cookie->header.instruction & 0x3F) != reply_header->instruction) {
*failureEntry |= (1 << RMAP_RX_FAIL_WRONG_REPLY);
return NULL;
}
return rxdesc;
}
void RmapSPWChannel::checkRxDescPacket(spw_rx_desc* rxdesc,
uint16_t* failureEntry) {
uint32_t statusword, len;
#ifdef LEON
asm("flush");
#endif
statusword = rxdesc->word0;
if ((statusword & (1 << SPW_DESC_RX_ENABLE)) || (statusword == 0)) {
return;
}
*failureEntry = 1 << RMAP_RX_FAIL_CHECKED;
if (statusword & (1 << SPW_DESC_RX_EEP)) {
*failureEntry |= (1 << RMAP_RX_FAIL_EEP);
return;
}
if (statusword & (1 << SPW_DESC_RX_TRUNCATED)) {
*failureEntry |= (1 << RMAP_RX_FAIL_TRUNC);
return;
}
len = statusword & 0x1FFFFFF;
if (!(len >= 13 || len == 8)) {
*failureEntry |= (1 << RMAP_RX_FAIL_LEN);
return;
}
if (checkCrc((uint8_t*) rxdesc->word1, len) != RETURN_OK) {
*failureEntry |= (1 << RMAP_RX_FAIL_CRC);
return;
}
checkRmapHeader((void *) rxdesc->word1, len, failureEntry);
}
ReturnValue_t RmapSPWChannel::checkCrc(uint8_t* packet, uint32_t len) {
if (len == 8) {
if (crc_calculate(packet, len) == 0) {
return RETURN_OK;
} else {
return RETURN_FAILED;
}
} else {
if ((crc_calculate(packet, RMAP_READ_REPLY_HEADER_LEN) == 0)
&& (crc_calculate(packet, len) == 0)) {
return RETURN_OK;
} else {
return RETURN_FAILED;
}
}
}
void RmapSPWChannel::checkRmapHeader(void* _header, uint32_t len,
uint16_t* failureEntry) {
RMAPStructs::rmap_read_reply_header *header =
(RMAPStructs::rmap_read_reply_header *) _header;
uint32_t datalen;
if (header->dest_address != src_addr) {
*failureEntry |= (1 << RMAP_RX_FAIL_DST_ADDR);
}
if (header->protocol != 0x01) {
*failureEntry |= (1 << RMAP_RX_FAIL_PROTO);
}
if (header->instruction & 0xC0) {
*failureEntry |= (1 << RMAP_RX_FAIL_INSTR_TYPE);
} else { //hope that works...
if ((!(header->instruction & (1 << RMAP_COMMAND_BIT_REPLY)))
|| ((header->instruction & (1 << RMAP_COMMAND_BIT_VERIFY))
&& (!(header->instruction
& (1 << RMAP_COMMAND_BIT_WRITE))))
|| (header->instruction & 3)) {
if (header->status == REPLY_UNUSED_PACKET_TYPE_OR_COMMAND_CODE) {
*failureEntry |= (1 << RMAP_RX_FAIL_INSTR);
} else {
*failureEntry |= (1 << RMAP_RX_FAIL_INSTR_TYPE);
}
}
}
if (header->instruction & (1 << RMAP_COMMAND_BIT_WRITE)) {
if (len != 8) {
*failureEntry |= (1 << RMAP_RX_FAIL_INSTR_TYPE);
}
} else {
if (len == 8) {
*failureEntry |= (1 << RMAP_RX_FAIL_INSTR_TYPE);
}
}
if (header->source_address != dest_addr) {
*failureEntry |= (1 << RMAP_RX_FAIL_SRC_ADDR);
}
if (len != 8) {
datalen = header->datalen_l | (header->datalen_m << 8)
| (header->datalen_h << 16);
if (datalen + RMAP_READ_REPLY_HEADER_LEN + 1 != len) {
*failureEntry |= (1 << RMAP_RX_FAIL_LEN_MISSMATCH);
}
}
}
ReturnValue_t RmapSPWChannel::sendCommandBlocking(RMAPCookie *cookie,
uint8_t *data, uint32_t datalen, uint8_t **databuffer, uint32_t *len,
uint32_t timeout_us) {
uint32_t time;
ReturnValue_t result;
if (databuffer != NULL) {
result = sendReadCommand(cookie, datalen);
} else {
result = sendWriteCommand(cookie, data, datalen);
}
if (result != RETURN_OK) {
return result;
}
time = hw_timer_get_us();
while (time - hw_timer_get_us() < timeout_us) {
result = getReply(cookie, databuffer, len);
if (!((result == REPLY_NOT_YET_SENT) || (result == REPLY_NO_REPLY))) {
return result;
}
}
if (result == REPLY_NOT_YET_SENT) {
return result;
}
return REPLY_TIMEOUT;
}
//SHOULDDO find a better way to inject the Extended address
#include <config/hardware/IoBoardAddresses.h>
ReturnValue_t RmapSPWChannel::open(Cookie **cookie, uint32_t address,
uint32_t maxReplyLen) {
*cookie = new RMAPCookie(address, IoBoardExtendedAddresses::DEVICE_BUFFER,
this, 0, maxReplyLen);
return RETURN_OK;
}
ReturnValue_t RmapSPWChannel::reOpen(Cookie* cookie, uint32_t address,
uint32_t maxReplyLen) {
ReturnValue_t result = isActive();
if (result != RETURN_OK) {
return result;
}
RMAPCookie *rCookie = dynamic_cast<RMAPCookie *>(cookie);
if (rCookie == NULL) {
return INVALID_COOKIE_TYPE;
}
rCookie->setAddress(address);
rCookie->setChannel(this);
rCookie->setCommandMask(0);
rCookie->setExtendedAddress(IoBoardExtendedAddresses::DEVICE_BUFFER);
rCookie->setMaxReplyLen(maxReplyLen);
return RETURN_OK;
}
void RmapSPWChannel::close(Cookie* cookie) {
delete cookie;
}
ReturnValue_t RmapSPWChannel::sendMessage(Cookie* cookie, uint8_t* data,
uint32_t len) {
return sendWriteCommand((RMAPCookie *) cookie, data, len);
}
ReturnValue_t RmapSPWChannel::getSendSuccess(Cookie* cookie) {
return getWriteReply((RMAPCookie *) cookie);
}
ReturnValue_t RmapSPWChannel::requestReceiveMessage(Cookie* cookie) {
return sendReadCommand((RMAPCookie *) cookie,
((RMAPCookie *) cookie)->getMaxReplyLen());
}
ReturnValue_t RmapSPWChannel::readReceivedMessage(Cookie* cookie,
uint8_t** buffer, uint32_t* size) {
return getReadReply((RMAPCookie *) cookie, buffer, size);
}
ReturnValue_t RmapSPWChannel::setAddress(Cookie* cookie, uint32_t address) {
((RMAPCookie *) cookie)->setAddress(address);
return HasReturnvaluesIF::RETURN_OK;
}
uint32_t RmapSPWChannel::getAddress(Cookie* cookie) {
return ((RMAPCookie *) cookie)->getAddress();
}
ReturnValue_t RmapSPWChannel::setParameter(Cookie* cookie, uint32_t parameter) {
return RETURN_FAILED;
}
uint32_t RmapSPWChannel::getParameter(Cookie* cookie) {
return 0;
}
void RmapSPWChannel::reportFailures(uint16_t failureEntry,
uint8_t descriptorNr) {
if (failureEntry & (1 << RMAP_RX_FAIL_CRC)) {
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_INVALID_DATA_CRC, descriptorNr);
}
if (failureEntry & (1 << RMAP_RX_FAIL_DST_ADDR)) {
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_INVALID_TARGET_LOGICAL_ADDRESS,
descriptorNr);
}
if (failureEntry & (1 << RMAP_RX_FAIL_EEP)) {
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_EEP, descriptorNr);
}
if (failureEntry & (1 << RMAP_RX_FAIL_INSTR)) {
triggerEvent(RMAP_PROTOCOL_ERROR,
REPLY_COMMAND_NOT_IMPLEMENTED_OR_NOT_AUTHORISED, descriptorNr);
}
if (failureEntry & (1 << RMAP_RX_FAIL_INSTR_TYPE)) {
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_RESERVED, descriptorNr);
}
if (failureEntry & (1 << RMAP_RX_FAIL_LEN)) {
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_TOO_MUCH_DATA, descriptorNr);
}
if (failureEntry & (1 << RMAP_RX_FAIL_LEN_MISSMATCH)) {
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_INVALID_DATA, descriptorNr);
}
if (failureEntry & (1 << RMAP_RX_FAIL_PROTO)) {
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_GENERAL_ERROR_CODE,
descriptorNr);
}
if (failureEntry & (1 << RMAP_RX_FAIL_SRC_ADDR)) {
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_GENERAL_ERROR_CODE,
descriptorNr);
}
if (failureEntry & (1 << RMAP_RX_FAIL_TRUNC)) {
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_TRANSMISSION_ERROR,
descriptorNr);
}
if (failureEntry & (1 << RMAP_RX_FAIL_WRONG_REPLY)) {
triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_INVALID_KEY, descriptorNr);
}
}
void RmapSPWChannel::reportSpwstr(uint32_t spwstr) {
if (spwstr & (1 << SPW_SPWSTR_CE)) {
triggerEvent(SPW_ERROR, SPW_CREDIT);
}
if (spwstr & (1 << SPW_SPWSTR_ER)) {
triggerEvent(SPW_ERROR, SPW_ESCAPE);
}
if (spwstr & (1 << SPW_SPWSTR_DE)) {
triggerEvent(SPW_ERROR, SPW_DISCONNECT);
}
if (spwstr & (1 << SPW_SPWSTR_PE)) {
triggerEvent(SPW_ERROR, SPW_PARITY);
}
if (spwstr & (1 << SPW_SPWSTR_WE)) {
triggerEvent(SPW_ERROR, SPW_WRITE_SYNC);
}
if (spwstr & (1 << SPW_SPWSTR_IA)) {
triggerEvent(SPW_ERROR, SPW_INVALID_ADDRESS);
}
if (spwstr & (1 << SPW_SPWSTR_EE)) {
triggerEvent(SPW_ERROR, SPW_EARLY_EOP);
}
}
uint8_t RmapSPWChannel::null_crc = 0;
int8_t RmapSPWChannel::getCurrentPortNr() {
uint8_t i;
int8_t oldport = -1;
for (i = 0; i < SPW_devices.len; ++i) {
if (SPW_devices.devices[i] == this->port) {
oldport = i;
}
}
return oldport;
}

View File

@ -1,135 +0,0 @@
#ifndef RMAPCHANNEL_H_
#define RMAPCHANNEL_H_
#include <framework/objectmanager/SystemObject.h>
#include <framework/rmap/RMAPChannelIF.h>
extern "C" {
#include <bsp_flp/spw/spw.h>
}
#include <config/datapool/dataPoolInit.h>
#include <framework/devicehandlers/DeviceCommunicationIF.h>
#include <framework/events/Event.h>
#include <framework/tasks/PeriodicTaskIF.h>
class RmapSPWChannel: public SystemObject,
public RMAPChannelIF,
public DeviceCommunicationIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CDH_1;
static const Event SPW_ERROR = MAKE_EVENT(0, SEVERITY::LOW);
static const Event SPW_LINK_DOWN = MAKE_EVENT(1, SEVERITY::LOW);
// static const Event SPW_CREDIT = MAKE_EVENT(1, SEVERITY::LOW);
// static const Event SPW_ESCAPE = MAKE_EVENT(2, SEVERITY::LOW);
// static const Event SPW_DISCONNECT = MAKE_EVENT(3, SEVERITY::LOW);
// static const Event SPW_PARITY = MAKE_EVENT(4, SEVERITY::LOW);
// static const Event SPW_WRITE_SYNC = MAKE_EVENT(5, SEVERITY::LOW);
// static const Event SPW_INVALID_ADDRESS = MAKE_EVENT(6, SEVERITY::LOW);
// static const Event SPW_EARLY_EOP = MAKE_EVENT(7, SEVERITY::LOW);
// static const Event SPW_DMA = MAKE_EVENT(8, SEVERITY::LOW);
// static const Event SPW_LINK_ERROR = MAKE_EVENT(9, SEVERITY::LOW);
static const Event RMAP_PROTOCOL_ERROR = MAKE_EVENT(10, SEVERITY::LOW);
// static const Event RMAP_CRC = MAKE_EVENT(10, SEVERITY::LOW);
// static const Event RMAP_DST_ADDR = MAKE_EVENT(11, SEVERITY::LOW);
// static const Event RMAP_EEP = MAKE_EVENT(12, SEVERITY::LOW);
// static const Event RMAP_INSTR = MAKE_EVENT(13, SEVERITY::LOW);
// static const Event RMAP_INSTR_TYPE = MAKE_EVENT(14, SEVERITY::LOW);
// static const Event RMAP_LEN = MAKE_EVENT(15, SEVERITY::LOW);
// static const Event RMAP_LEN_MISSMATCH = MAKE_EVENT(16, SEVERITY::LOW);
// static const Event RMAP_PROTO = MAKE_EVENT(17, SEVERITY::LOW);
// static const Event RMAP_SRC_ADDR = MAKE_EVENT(18, SEVERITY::LOW);
// static const Event RMAP_TRUNC = MAKE_EVENT(19, SEVERITY::LOW);
// static const Event RMAP_WRONG_REPLY = MAKE_EVENT(20, SEVERITY::LOW);
static const Event RMAP_MISSED_REPLIES = MAKE_EVENT(21, SEVERITY::LOW);
static const Event RMAP_NO_RX_DESCRIPTORS = MAKE_EVENT(22, SEVERITY::LOW);
static const Event RMAP_NO_TX_DESCRIPTORS = MAKE_EVENT(23, SEVERITY::LOW);
static const Event RMAP_SWITCHED_PORT = MAKE_EVENT(24, SEVERITY::INFO);
RmapSPWChannel(object_id_t setObjectId, uint16_t buffersize_words,
uint32_t maxPacketSize, int8_t portNr, uint8_t dest_addr,
uint8_t src_addr, PeriodicTaskIF* currentTask, datapool::opus_variable_id portVariable =
datapool::NO_PARAMETER);
virtual ~RmapSPWChannel();
virtual ReturnValue_t reset();
virtual ReturnValue_t isActive();
virtual ReturnValue_t setPort(int8_t port, uint8_t dest_addr,
uint8_t src_addr, PeriodicTaskIF* currentTask);
virtual ReturnValue_t setPort(int8_t port, PeriodicTaskIF* currentTask);
virtual ReturnValue_t sendCommand(RMAPCookie *cookie, uint8_t instruction,
uint8_t *data, uint32_t datalen);
virtual ReturnValue_t getReply(RMAPCookie *cookie, uint8_t **databuffer,
uint32_t *len);
virtual ReturnValue_t sendCommandBlocking(RMAPCookie *cookie, uint8_t *data,
uint32_t datalen, uint8_t **databuffer, uint32_t *len,
uint32_t timeout_us);
virtual ReturnValue_t open(Cookie **cookie, uint32_t address,
uint32_t maxReplyLen);
virtual ReturnValue_t reOpen(Cookie *cookie, uint32_t address,
uint32_t maxReplyLen);
virtual void close(Cookie *cookie);
virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data,
uint32_t len);
virtual ReturnValue_t getSendSuccess(Cookie *cookie);
virtual ReturnValue_t requestReceiveMessage(Cookie *cookie);
virtual ReturnValue_t readReceivedMessage(Cookie *cookie, uint8_t **buffer,
uint32_t *size);
virtual ReturnValue_t setAddress(Cookie *cookie, uint32_t address);
virtual uint32_t getAddress(Cookie *cookie);
virtual ReturnValue_t setParameter(Cookie *cookie, uint32_t parameter);
virtual uint32_t getParameter(Cookie *cookie);
private:
SPW_dev *port;
uint32_t *buffer;
uint32_t *buffer_pointer; //points to the next free space in the buffer
uint32_t *end_of_buffer; //points to the word AFTER the buffer
spw_tx_desc *tx_descriptor_table;
spw_rx_desc *rx_descriptor_table;
uint16_t *failure_table;
uint32_t max_packet_len;
uint16_t tid;
// uint8_t port_has_crc;
uint8_t rx_index; //index of the next unused rx descriptor
uint8_t max_rx;
uint8_t tx_index; //index of the next unused tx descriptor
uint8_t max_tx;
uint8_t src_addr;
uint8_t dest_addr;
datapool::opus_variable_id portPoolId;
static uint8_t null_crc;
spw_rx_desc *findReply(RMAPCookie *cookie);
ReturnValue_t checkTxDesc(RMAPCookie *cookie);
spw_rx_desc *checkRxDesc(RMAPCookie *cookie, uint8_t rxdesc_index);
void checkRxDescPacket(spw_rx_desc *rxdesc, uint16_t *failureEntry);
ReturnValue_t checkCrc(uint8_t *packet, uint32_t len);
void checkRmapHeader(void *_header, uint32_t len, uint16_t *failureEntry);
void reportFailures(uint16_t failureEntry, uint8_t descriptorNr);
void reportSpwstr(uint32_t spwstr);
int8_t getCurrentPortNr();
};
#endif /* RMAPCHANNEL_H_ */

View File

@ -7,28 +7,45 @@
//////////////////////////////////////////////////////////////////////////////////
// RMAP command bits
#define RMAP_COMMAND_BIT_INCREMENT 2
#define RMAP_COMMAND_BIT_REPLY 3
#define RMAP_COMMAND_BIT_WRITE 5
#define RMAP_COMMAND_BIT_VERIFY 4
#define RMAP_COMMAND_BIT 6
//#define RMAP_COMMAND_BIT_INCREMENT 2
//#define RMAP_COMMAND_BIT_REPLY 3
//#define RMAP_COMMAND_BIT_WRITE 5
//#define RMAP_COMMAND_BIT_VERIFY 4
//#define RMAP_COMMAND_BIT 6
namespace RMAPIds{
static const uint8_t RMAP_COMMAND_BIT_INCREMENT = 2;
static const uint8_t RMAP_COMMAND_BIT_REPLY = 3;
static const uint8_t RMAP_COMMAND_BIT_WRITE = 5;
static const uint8_t RMAP_COMMAND_BIT_VERIFY = 4;
static const uint8_t RMAP_COMMAND_BIT = 6;
//////////////////////////////////////////////////////////////////////////////////
// RMAP commands
#define RMAP_COMMAND_WRITE ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY))
static const uint8_t RMAP_COMMAND_WRITE = ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY));
static const uint8_t RMAP_COMMAND_READ = ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_REPLY));
static const uint8_t RMAP_REPLY_WRITE = ((1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY));
static const uint8_t RMAP_REPLY_READ = ((1<<RMAP_COMMAND_BIT_REPLY));
//#define RMAP_COMMAND_WRITE ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY))
//#define RMAP_COMMAND_WRITE_VERIFY ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY))
#define RMAP_COMMAND_READ ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_REPLY))
//#define RMAP_COMMAND_READ ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_REPLY))
#define RMAP_REPLY_WRITE ((1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY))
//#define RMAP_REPLY_WRITE ((1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY))
//#define RMAP_REPLY_WRITE_VERIFY ((1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY))
#define RMAP_REPLY_READ ((1<<RMAP_COMMAND_BIT_REPLY))
//#define RMAP_REPLY_READ ((1<<RMAP_COMMAND_BIT_REPLY))
//////////////////////////////////////////////////////////////////////////////////
// useful info
#define RMAP_COMMAND_HEADER_LEN 16
#define RMAP_WRITE_REPLY_HEADER_LEN 8
#define RMAP_READ_REPLY_HEADER_LEN 12
static const uint8_t RMAP_COMMAND_HEADER_LEN = 16;
static const uint8_t RMAP_WRITE_REPLY_HEADER_LEN = 8;
static const uint8_t RMAP_READ_REPLY_HEADER_LEN = 12;
static const uint8_t RMAP_DATA_FOOTER_SIZE = 1; //SIZE OF CRC
//#define RMAP_COMMAND_HEADER_LEN 16
//#define RMAP_WRITE_REPLY_HEADER_LEN 8
//#define RMAP_READ_REPLY_HEADER_LEN 12
}
namespace RMAPStructs {
struct rmap_cmd_header {