Today's the day. Renamed platform to framework.

This commit is contained in:
Bastian Baetz
2016-06-15 23:48:41 +02:00
committed by Ulrich Mohr
parent 40987d0b27
commit 1d22a6c97e
356 changed files with 33946 additions and 3 deletions

91
rmap/RMAP.cpp Normal file
View File

@ -0,0 +1,91 @@
#include <framework/devicehandlers/DeviceCommunicationIF.h>
#include <framework/rmap/rmapStructs.h>
#include <framework/rmap/RMAP.h>
#include <framework/rmap/RMAPChannelIF.h>
#include <stddef.h>
ReturnValue_t RMAP::reset(RMAPCookie* cookie) {
return cookie->channel->reset();
}
//TODO Check for channel == NULL
//Done. BB
RMAP::RMAP(){
}
ReturnValue_t RMAP::sendWriteCommand(RMAPCookie *cookie, uint8_t* buffer,
uint32_t length) {
uint8_t instruction;
if ((buffer == NULL) && (length != 0)) {
return DeviceCommunicationIF::NULLPOINTER;
}
if (cookie->getChannel() == NULL) {
return COMMAND_NO_CHANNEL;
}
instruction = RMAP_COMMAND_WRITE | cookie->command_mask;
return cookie->getChannel()->sendCommand(cookie, instruction, buffer,
length);
}
ReturnValue_t RMAP::getWriteReply(RMAPCookie *cookie) {
if (cookie->getChannel() == NULL) {
return COMMAND_NO_CHANNEL;
}
if (cookie->header.instruction & (1 << RMAP_COMMAND_BIT_WRITE)) {
return cookie->getChannel()->getReply(cookie, NULL, NULL);
} else {
return REPLY_MISSMATCH;
}
}
ReturnValue_t RMAP::writeBlocking(RMAPCookie *cookie, uint8_t* buffer,
uint32_t length, uint32_t timeout_us) {
if (cookie->getChannel() == NULL) {
return COMMAND_NO_CHANNEL;
}
return cookie->getChannel()->sendCommandBlocking(cookie, buffer, length,
NULL, NULL, timeout_us);
}
ReturnValue_t RMAP::sendReadCommand(RMAPCookie *cookie, uint32_t expLength) {
uint8_t command;
if (cookie->getChannel() == NULL) {
return COMMAND_NO_CHANNEL;
}
command = RMAP_COMMAND_READ
| (cookie->command_mask & ~(1 << RMAP_COMMAND_BIT_VERIFY));
return cookie->getChannel()->sendCommand(cookie, command, NULL, expLength);
}
ReturnValue_t RMAP::getReadReply(RMAPCookie *cookie, uint8_t **buffer,
uint32_t *size) {
if (cookie->getChannel() == NULL) {
return COMMAND_NO_CHANNEL;
}
if (buffer == NULL || size == NULL) {
return DeviceCommunicationIF::NULLPOINTER;
}
if (cookie->header.instruction & (1 << RMAP_COMMAND_BIT_WRITE)) {
return REPLY_MISSMATCH;
} else {
return cookie->getChannel()->getReply(cookie, buffer, size);
}
}
ReturnValue_t RMAP::readBlocking(RMAPCookie *cookie, uint32_t expLength,
uint8_t** buffer, uint32_t *size, uint32_t timeout_us) {
if (cookie->getChannel() == NULL) {
return COMMAND_NO_CHANNEL;
}
if (buffer == NULL || size == NULL) {
return DeviceCommunicationIF::NULLPOINTER;
}
return cookie->getChannel()->sendCommandBlocking(cookie, NULL, expLength,
buffer, size, timeout_us);
}

226
rmap/RMAP.h Normal file
View File

@ -0,0 +1,226 @@
#ifndef RMAPpp_H_
#define RMAPpp_H_
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/rmap/RMAPCookie.h>
//TODO: clean up includes for RMAP, should be enough to include RMAP.h but right now it's quite chaotic...
/**
* API for a Cookie/Channel based RMAP implementation.
*
* The API offers the four basic RMAP actions: sending a Read or Write command and getting the reply to each.
* As RMAP is an asynchronous protocol, these are implemented as four seperate calls. There are blocking
* calls which combine a send and get call using a timeout, but these are "real" blocking, looping in between
* the calls.
*
* Cookies are used to contain Information between a send[Read,Write]Command and a get[Read,Write]Reply call,
* one can think of them like *nix file descriptors. A cookie is valid from a sendX call until the related getX
* call. That means if a cookie is used in a getX call, the reply to the sendX call the cookie was used with
* previously is returned.
* Depending on the underlying RMAPChannel implementation, a cookie can also be valid for more than one getX
* call, but this should not be assumed generally.
* A cookie encapsulates information like the RMAP Channel to use, as well as the RMAP Address
* and a Command Mask used for specifying which RMAP capabilities are used.
* Cookies are created without interaction with this API, there is no open() call. The RMAP implementation
* will initialize all fields which are not set by the cookie's constructor.
*
* The RMAP implementation relies on Channels. A channel is used to construct the RMAP Headers and handle the
* protocol. It is access via the RMAPChannelIF. Thus it is possible to use different Implementations which only
* need to implement the RMAPChannelIF. A channel is also responsible for accessing the lower layers, for example
* a SPaceWire transport layer.
*
* There is one RMAP Channel per physical device. The cookie-channel as well as the device-channel assignment
* can be changed at runtime to allow for example redundancy switching. This API is static as the information which
* channel to use is contained within the cookie.
*/
class RMAP: public HasReturnvaluesIF {
public:
static const uint8_t INTERFACE_ID = RMAP_CHANNEL;
//static const ReturnValue_t COMMAND_OK = MAKE_RETURN_CODE(0x00);
static const ReturnValue_t COMMAND_NO_DESCRIPTORS_AVAILABLE =
MAKE_RETURN_CODE(0xE1); //no descriptors available for sending command; command was not sent
static const ReturnValue_t COMMAND_BUFFER_FULL = MAKE_RETURN_CODE(0xE2); //no receiver buffer available for expected len; command was not sent
static const ReturnValue_t COMMAND_CHANNEL_OUT_OF_RANGE = MAKE_RETURN_CODE(
0xE3); //The cookie points to an invalid channel; command was not sent
//Replaced by DeviceCommunicationIF::TOO_MUCH_DATA static const ReturnValue_t COMMAND_TOO_BIG = MAKE_RETURN_CODE(0xE4); //the data that was to be sent was too long for the hw to handle (write command) or the expected len was bigger than maximal expected len (read command)
//command was not sent
//replaced by DeviceCommunicationIF::NULLPOINTER static const ReturnValue_t COMMAND_NULLPOINTER = MAKE_RETURN_CODE(0xE5); //datalen was != 0 but data was == NULL in write command, or nullpointer in read command
static const ReturnValue_t COMMAND_CHANNEL_DEACTIVATED = MAKE_RETURN_CODE(
0xE6); //the channel has no port set
static const ReturnValue_t COMMAND_PORT_OUT_OF_RANGE = MAKE_RETURN_CODE(
0xE7); //The specified port is not valid
static const ReturnValue_t COMMAND_PORT_IN_USE = MAKE_RETURN_CODE(0xE8);//The specified port is already in use
static const ReturnValue_t COMMAND_NO_CHANNEL = MAKE_RETURN_CODE(0xE9);//The cookie to work with has no channel assigned.
//return values for both get_write_reply and get_read_reply
static const ReturnValue_t REPLY_NO_REPLY = MAKE_RETURN_CODE(0xD0); //no reply was received
static const ReturnValue_t REPLY_NOT_SENT = MAKE_RETURN_CODE(0xD1); //command was not sent, implies no reply
static const ReturnValue_t REPLY_NOT_YET_SENT = MAKE_RETURN_CODE(0xD2); //command is still waiting to be sent
static const ReturnValue_t REPLY_MISSMATCH = MAKE_RETURN_CODE(0xD3);//a read command was issued, but get_write_rply called, or other way round
static const ReturnValue_t REPLY_TIMEOUT = MAKE_RETURN_CODE(0xD4);//timeout
//replaced by DeviceCommunicationIF::NULLPOINTER static const ReturnValue_t REPLY_NULLPOINTER = MAKE_RETURN_CODE(0xD5);//one of the arguments in a read reply was NULL
//return values for get_reply
static const ReturnValue_t REPLY_INTERFACE_BUSY = MAKE_RETURN_CODE(
0xC0);//Interface is busy (transmission buffer still being processed)
static const ReturnValue_t REPLY_TRANSMISSION_ERROR =
MAKE_RETURN_CODE(0xC1); //Interface encountered errors during last operation, data could not be processed. (transmission error)
static const ReturnValue_t REPLY_INVALID_DATA = MAKE_RETURN_CODE(
0xC2); //Invalid data (amount / value)
static const ReturnValue_t REPLY_NOT_SUPPORTED = MAKE_RETURN_CODE(
0xC3);
//return values for reset
static const ReturnValue_t LINK_DOWN = MAKE_RETURN_CODE(0xF0);//The spw link is down
//Other SpW codes:
static const ReturnValue_t SPW_CREDIT = MAKE_RETURN_CODE(0xF1);
static const ReturnValue_t SPW_ESCAPE = MAKE_RETURN_CODE(0xF2);
static const ReturnValue_t SPW_DISCONNECT = MAKE_RETURN_CODE(0xF3);
static const ReturnValue_t SPW_PARITY = MAKE_RETURN_CODE(0xF4);
static const ReturnValue_t SPW_WRITE_SYNC = MAKE_RETURN_CODE(0xF5);
static const ReturnValue_t SPW_INVALID_ADDRESS = MAKE_RETURN_CODE(0xF6);
static const ReturnValue_t SPW_EARLY_EOP = MAKE_RETURN_CODE(0xF7);
static const ReturnValue_t SPW_DMA = MAKE_RETURN_CODE(0xF8);
static const ReturnValue_t SPW_LINK_ERROR = MAKE_RETURN_CODE(0xF9);
//RMAP standard replies
static const ReturnValue_t REPLY_OK = MAKE_RETURN_CODE(0);
static const ReturnValue_t REPLY_GENERAL_ERROR_CODE = MAKE_RETURN_CODE(1);// The detected error does not fit into the other
// error cases or the node does not support
// further distinction between the errors
static const ReturnValue_t REPLY_UNUSED_PACKET_TYPE_OR_COMMAND_CODE =
MAKE_RETURN_CODE(2); // The Header CRC was decoded correctly but
// the packet type is reserved or the command
// is not used by the RMAP protocol.
static const ReturnValue_t REPLY_INVALID_KEY = MAKE_RETURN_CODE(3); // The Header CRC was decoded correctly but
// the device key did not match that expected
// by the target user application
static const ReturnValue_t REPLY_INVALID_DATA_CRC = MAKE_RETURN_CODE(4);// Error in the CRC of the data field
static const ReturnValue_t REPLY_EARLY_EOP = MAKE_RETURN_CODE(5);// EOP marker detected before the end of the data
static const ReturnValue_t REPLY_TOO_MUCH_DATA = MAKE_RETURN_CODE(6);// More than the expected amount of data in a
// command has been received
static const ReturnValue_t REPLY_EEP = MAKE_RETURN_CODE(7); // EEP marker detected immediately after the
// header CRC or during the transfer of data
// and Data CRC or immediately thereafter.
// Indicates that there was a communication
// failure of some sort on the network
static const ReturnValue_t REPLY_RESERVED = MAKE_RETURN_CODE(8);// Reserved
static const ReturnValue_t REPLY_VERIFY_BUFFER_OVERRUN = MAKE_RETURN_CODE(
9); // The verify before write bit of the command
// was set so that the data field was buffered in
// order to verify the Data CRC before
// transferring the data to target memory. The
// data field was longer than able to fit inside
// the verify buffer resulting in a buffer overrun
// Note that the command is not executed in
// this case
static const ReturnValue_t REPLY_COMMAND_NOT_IMPLEMENTED_OR_NOT_AUTHORISED =
MAKE_RETURN_CODE(10);// The target user application did not authorise
// the requested operation. This may be because
// the command requested has not been
// implemented
static const ReturnValue_t REPLY_RMW_DATA_LENGTH_ERROR = MAKE_RETURN_CODE(
11); // The amount of data in a RMW command is
// invalid (0x01 0x03 0x05 0x07 or greater
// than 0x08)
static const ReturnValue_t REPLY_INVALID_TARGET_LOGICAL_ADDRESS =
MAKE_RETURN_CODE(12); // The Header CRC was decoded correctly but
// the Target Logical Address was not the value
// expected by the target
/**
* Resets the underlying channel.
*
* @param cookie The cookie which points to the channel to reset
* @return
*/
static ReturnValue_t reset(RMAPCookie *cookie);
/**
* send an RMAP write command
*
* datalen is only 24bit wide, rest will be ignored
* IMPORTANT: the data buffer must be datalen+1 large, as the driver might
* write a CRC sum at data[datalen]
* if you want to send an empty packet, just do datalen = 0 and data = NULL
*
* @param cookie The cookie to write to
* @param buffer the data to write
* @param length length of data
* @return
* - @c COMMAND_NULLPOINTER datalen was != 0 but data was == NULL in write command
* - return codes of RMAPChannelIF::sendCommand()
*/
static ReturnValue_t sendWriteCommand(RMAPCookie *cookie, uint8_t* buffer,
uint32_t length);
/**
* get the reply to a write command
*
* @param cookie the cookie the command was sent with
* @return
* - @c REPLY_MISSMATCH a read command was issued, but getWriteReply called
* - return codes of RMAPChannelIF::getReply()
*/
static ReturnValue_t getWriteReply(RMAPCookie *cookie);
/**
* @see sendWriteCommand()
* @see getWriteReply()
*
* @param timeout_us the time after the function returns, if no reply was received
*
* @return
* - All of sendWriteCommand()
* - All of getWriteReply()
* - @c REPLY_TIMEOUT timeout
*/
static ReturnValue_t writeBlocking(RMAPCookie *cookie, uint8_t* buffer,
uint32_t length, uint32_t timeout_us);
/**
* send an RMAP read command
*
* @param cookie to cookie to read from
* @param expLength the expected maximum length of the reply
* @return
* - @c COMMAND_NULLPOINTER datalen was != 0 but data was == NULL in write command, or nullpointer in read command
* - return codes of RMAPChannelIF::sendCommand()
*/
static ReturnValue_t sendReadCommand(RMAPCookie *cookie,
uint32_t expLength);
/**
* get a reply to an RMAP read command
*
* @param cookie the cookie that was read from
* @param[out] buffer the location of the data
* @param[out] size size of the data
* @return
* - @c COMMAND_NULLPOINTER buffer or size was NULL
* - @c REPLY_MISSMATCH a write command was issued, but getReadReply called
* - return codes of RMAPChannelIF::getReply()
*/
static ReturnValue_t getReadReply(RMAPCookie *cookie, uint8_t **buffer,
uint32_t *size);
/**
* @see sendReadCommand()
* @see getReadReply()
*
* @param timeout_us the time after the function returns, if no reply was received
*
* @return
* - All of sendReadCommand()
* - All of getReadReply()
* - @c REPLY_TIMEOUT timeout
*/
static ReturnValue_t readBlocking(RMAPCookie *cookie, uint32_t expLength,
uint8_t** buffer, uint32_t *size, uint32_t timeout_us);
protected:
RMAP();
};
#endif /* RMAPpp_H_ */

120
rmap/RMAPChannelIF.h Normal file
View File

@ -0,0 +1,120 @@
/*
* RMAPChannelIF.h
*
* Created on: 31.05.2013
* Author: tod
*/
#ifndef RMAPCHANNELIF_H_
#define RMAPCHANNELIF_H_
#include <framework/rmap/RMAP.h>
class RMAPChannelIF: public RMAP {
public:
/**
* Reset an RMAP channel
*
* Clears the receive buffer (all received messages are deleted) and resets the descriptor table.
* Also checks for errors in the descriptors and submits them to FDIR (aka stdout)
*
* @param channel to reset
*
* @return
* - @c LINK_DOWN when the link is down and all replies were missed
* - @c COMMAND_CHANNEL_DEACTIVATED if the channel's port is NULL
* - @c RETURN_OK else
*/
virtual ReturnValue_t reset()=0;
/**
* Check if a channel is active (ie has a port)
*
* @param channel_nr
* @return
* - @c COMMAND_OK if channel is active
* - @c COMMAND_CHANNEL_DEACTIVATED if channel is deactivated
*/
virtual ReturnValue_t isActive()=0;
/**
* Assign a SpaceWire port to the Channel
*
* @param port Number of the port. SpaceWire devices are mapped to port numbers to allow checking of the validity
* @param dest_addr the destination address used by all packets sent from this channel
* @param src_addr the source address used by all packets sent from this channel and used when checking incoming packets
* @return
* - @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, uint8_t dest_addr,
uint8_t src_addr)=0;
/**
* Assign a SpaceWire port to the Channel
*
* same as setPort(int8_t port, uint8_t dest_addr, uint8_t src_addr), only the addresses are left unchanged
*
* @param port Number of the port. SpaceWire devices are mapped to port numbers to allow checking of the validity
* @return
* - @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)=0;
/**
* Send an RMAP command
*
* @param cookie the cookie used with this call
* @param instruction the instruction byte that will be sent (this defines if it is a read or write command)
* @param data data to be sent
* @param datalen length of data
* @return
* - @c RETURN_OK
* - @c COMMAND_NO_DESCRIPTORS_AVAILABLE no descriptors available for sending command; command was not sent
* - @c COMMAND_BUFFER_FULL no receiver buffer available for expected len; command was not sent
* - @c COMMAND_TOO_BIG the data that was to be sent was too long for the hw to handle (write command) or the expected len was bigger than maximal expected len (read command) command was not sent
* - @c COMMAND_CHANNEL_DEACTIVATED the channel has no port set
* - @c NOT_SUPPORTED if you dont feel like implementing something...
*/
virtual ReturnValue_t sendCommand(RMAPCookie *cookie, uint8_t instruction,
uint8_t *data, uint32_t datalen)=0;
/**
* get the reply to an rmap command
*
* @param cookie the cookie the command was sent with
* @param databuffer a pointer to a pointer the location of the reply will be written to
* @param len a pointer to the variable the length of the reply will be written to
* @return
* - @c REPLY_NO_REPLY no reply was received
* - @c REPLY_NOT_SENT command was not sent, implies no reply
* - @c REPLY_NOT_YET_SENT command is still waiting to be sent
* - @c WRITE_REPLY_INTERFACE_BUSY Interface is busy (transmission buffer still being processed)
* - @c WRITE_REPLY_TRANSMISSION_ERROR Interface encountered errors during last operation, data could not be processed. (transmission error)
* - @c WRITE_REPLY_INVALID_DATA Invalid data (amount / value)
* - @c WRITE_REPLY_NOT_SUPPORTED
* - all RMAP standard replies
*/
virtual ReturnValue_t getReply(RMAPCookie *cookie, uint8_t **databuffer,
uint32_t *len)=0;
/**
*
* @param cookie
* @param data
* @param datalen
* @param databuffer
* @param len
* @param timeout_us
* @return
* - all replies of sendCommand() and getReply()
* - @c REPLY_TIMEOUT timeout
*/
virtual ReturnValue_t sendCommandBlocking(RMAPCookie *cookie, uint8_t *data,
uint32_t datalen, uint8_t **databuffer, uint32_t *len,
uint32_t timeout_us)=0;
};
#endif /* RMAPCHANNELIF_H_ */

113
rmap/RMAPCookie.cpp Normal file
View File

@ -0,0 +1,113 @@
/*
* RMAPcpp
*
* Created on: 07.11.2012
* Author: mohr
*/
#include <framework/rmap/RMAPChannelIF.h>
#include <framework/rmap/RMAPCookie.h>
#include <stddef.h>
//TODO use ctor initialization list
RMAPCookie::RMAPCookie() {
this->header.dest_address = 0;
this->header.protocol = 0x01;
this->header.instruction = 0;
this->header.dest_key = 0;
this->header.source_address = 0;
this->header.tid_h = 0;
this->header.tid_l = 0;
this->header.extended_address = 0;
this->header.address_hh = 0;
this->header.address_h = 0;
this->header.address_l = 0;
this->header.address_ll = 0;
this->header.datalen_h = 0;
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->maxReplyLen = 0;
}
RMAPCookie::RMAPCookie(uint32_t set_address, uint8_t set_extended_address,
RMAPChannelIF *set_channel, uint8_t set_command_mask, uint32_t maxReplyLen) {
this->header.dest_address = 0;
this->header.protocol = 0x01;
this->header.instruction = 0;
this->header.dest_key = 0;
this->header.source_address = 0;
this->header.tid_h = 0;
this->header.tid_l = 0;
this->header.extended_address = set_extended_address;
setAddress(set_address);
this->header.datalen_h = 0;
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->maxReplyLen = maxReplyLen;
}
void RMAPCookie::setAddress(uint32_t address) {
this->header.address_hh = (address & 0xFF000000) >> 24;
this->header.address_h = (address & 0x00FF0000) >> 16;
this->header.address_l = (address & 0x0000FF00) >> 8;
this->header.address_ll = address & 0x000000FF;
}
void RMAPCookie::setExtendedAddress(uint8_t extendedAddress) {
this->header.extended_address = extendedAddress;
}
void RMAPCookie::setChannel(RMAPChannelIF *channel) {
this->channel = channel;
}
void RMAPCookie::setCommandMask(uint8_t commandMask) {
this->command_mask = commandMask;
}
uint32_t RMAPCookie::getAddress() {
return (header.address_hh << 24) + (header.address_h << 16)
+ (header.address_l << 8) + (header.address_ll);
}
uint8_t RMAPCookie::getExtendedAddress() {
return header.extended_address;
}
RMAPChannelIF *RMAPCookie::getChannel() {
return channel;
}
uint8_t RMAPCookie::getCommandMask() {
return command_mask;
}
RMAPCookie::~RMAPCookie() {
}
uint32_t RMAPCookie::getMaxReplyLen() const {
return maxReplyLen;
}
void RMAPCookie::setMaxReplyLen(uint32_t maxReplyLen) {
this->maxReplyLen = maxReplyLen;
}

50
rmap/RMAPCookie.h Normal file
View File

@ -0,0 +1,50 @@
/*
* RMAPCookie.h
*
* Created on: 07.11.2012
* Author: mohr
*/
#ifndef RMAPCOOKIE_H_
#define RMAPCOOKIE_H_
#include <framework/devicehandlers/Cookie.h>
#include <framework/rmap/rmapStructs.h>
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();
RMAPCookie(uint32_t set_address, uint8_t set_extended_address,
RMAPChannelIF *set_channel, uint8_t set_command_mask, uint32_t maxReplyLen = 0);
virtual ~RMAPCookie();
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();
protected:
RMAPStructs::rmap_cmd_header header;
void *txdesc;
uint8_t rxdesc_index;
RMAPChannelIF *channel;
uint8_t command_mask;
uint32_t maxReplyLen;
};
#endif /* RMAPCOOKIE_H_ */

774
rmap/RmapSPWChannel.cpp Normal file
View File

@ -0,0 +1,774 @@
/*
* RMAPStack.cpp
*
* Created on: 30.05.2013
* Author: tod
*/
#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,
datapool::opus_variable_id portVariable) :
SystemObject(setObjectId), port(NULL), port_has_crc(0), 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);
}
RmapSPWChannel::~RmapSPWChannel() {
delete[] buffer;
delete[] failure_table;
}
ReturnValue_t RmapSPWChannel::reset() {
uint8_t link_down = 0;
uint8_t missed, i;
uint32_t state;
//printf_sif_rmap("reset channel %i\n", channel_nr);
//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++;
}
//TODO: checkme
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) {
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;
}
if (portNr != -1) {
new_port = SPW_devices.devices[portNr];
} 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);
//check if crc is enabled
port_has_crc = spw_crc_enabled(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);
OSAL::sleepFor(10);
reset();
return RETURN_OK;
}
ReturnValue_t RmapSPWChannel::setPort(int8_t port) {
return setPort(port, this->dest_addr, this->src_addr);
}
spw_rx_desc* RmapSPWChannel::findReply(RMAPCookie* cookie) {
spw_rx_desc *rxdesc;
uint8_t i;
//look downwards
//TODO: checkme
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
}
//calculate crc if not done in hw
if (!port_has_crc) {
cookie->header.header_crc = crc_calculate((uint8_t *) &cookie->header,
RMAP_COMMAND_HEADER_LEN - 1);
headerlen = RMAP_COMMAND_HEADER_LEN;
if (instruction & (1 << RMAP_COMMAND_BIT_WRITE)) {
if (datalen == 0) {
data = &null_crc;
} else {
data[datalen] = crc_calculate(data, datalen);
}
datalen++;
}
}
//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 (port_has_crc) {
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);
}
} else {
tx_descriptor_table[tx_index].word0 = headerlen
| (1 << SPW_DESC_TX_ENABLE);
}
//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);
// printf_sif("Reached critical entry.\n");
*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;
}
//TODO 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 REPLY_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) {
//TODO: Communicate to Kai, adjust return codes.
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) {
//TODO: Communicate to Kai.
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;
}

141
rmap/RmapSPWChannel.h Normal file
View File

@ -0,0 +1,141 @@
/*
* RMAPStack.h
*
* Created on: 30.05.2013
* Author: tod
*/
#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>
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, 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);
virtual ReturnValue_t setPort(int8_t port);
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_ */

88
rmap/rmapStructs.h Normal file
View File

@ -0,0 +1,88 @@
/*
* rmapStructs.h
*
* Created on: 30.05.2013
* Author: tod
*/
#ifndef RMAPSTRUCTS_H_
#define RMAPSTRUCTS_H_
#include <stdint.h>
//TODO: having the defines within a namespace would be nice. Problem are the defines referencing the previous define, eg RMAP_COMMAND_WRITE
//////////////////////////////////////////////////////////////////////////////////
// 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
//////////////////////////////////////////////////////////////////////////////////
// RMAP commands
#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_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))
//////////////////////////////////////////////////////////////////////////////////
// useful info
#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 {
uint8_t dest_address;
uint8_t protocol;
uint8_t instruction;
uint8_t dest_key;
uint8_t source_address;
uint8_t tid_h;
uint8_t tid_l;
uint8_t extended_address;
uint8_t address_hh;
uint8_t address_h;
uint8_t address_l;
uint8_t address_ll;
uint8_t datalen_h;
uint8_t datalen_m;
uint8_t datalen_l;
uint8_t header_crc;
};
struct rmap_read_reply_header {
uint8_t dest_address;
uint8_t protocol;
uint8_t instruction;
uint8_t status;
uint8_t source_address;
uint8_t tid_h;
uint8_t tid_l;
uint8_t reserved;
uint8_t datalen_h;
uint8_t datalen_m;
uint8_t datalen_l;
uint8_t header_crc;
};
struct rmap_write_reply_header {
uint8_t dest_address;
uint8_t protocol;
uint8_t instruction;
uint8_t status;
uint8_t source_address;
uint8_t tid_h;
uint8_t tid_l;
uint8_t header_crc;
};
}
#endif /* RMAPSTRUCTS_H_ */