OpenCores
URL https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [libdbg64g/] [services/] [debug/] [edcl.cpp] - Rev 5

Compare with Previous | Blame | View Log

/**
 * @file
 * @copyright  Copyright 2016 GNSS Sensor Ltd. All right reserved.
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
 * @brief      Access to a hardware via Ethernet EDCL interface implementaion.
 */
 
#include "edcl_types.h"
#include "edcl.h"
 
namespace debugger {
 
/** Class registration in the Core */
REGISTER_CLASS(EdclService)
 
EdclService::EdclService(const char *name) : IService(name) {
    registerInterface(static_cast<ITap *>(this));
    registerAttribute("Transport", &transport_);
    registerAttribute("seq_cnt", &seq_cnt_);
    seq_cnt_.make_uint64(0);
    itransport_ = 0;
 
    dbgRdTRansactionCnt_ = 0;
}
 
void EdclService::postinitService() {
    IService *iserv = 
        static_cast<IService *>(RISCV_get_service(transport_.to_string()));
    if (!iserv) {
        RISCV_error("Transport service '%'s not found", 
                    transport_.to_string());
    }
    itransport_ = static_cast<ILink *>(iserv->getInterface(IFACE_LINK));
    if (!itransport_) {
        RISCV_error("UDP interface '%s' not found", 
                     transport_.to_string());
    }
}
 
int EdclService::read(uint64_t addr, int bytes, uint8_t *obuf) {
    int txoff, rxoff;
    UdpEdclCommonType req = {0};
    UdpEdclCommonType rsp;
 
    if (!itransport_) {
        RISCV_error("UDP transport not defined, addr=%x", addr);
        return TAP_ERROR;
    }
 
    int rd_bytes = 0;
    while (rd_bytes < bytes && rd_bytes != TAP_ERROR) {
        req.control.request.seqidx = 
                    static_cast<uint32_t>(seq_cnt_.to_uint64());
        req.control.request.write = 0;
        req.address = static_cast<uint32_t>(addr + rd_bytes);
        if ((bytes - rd_bytes) > EDCL_PAYLOAD_MAX_BYTES) {
            req.control.request.len = 
                    static_cast<uint32_t>(EDCL_PAYLOAD_MAX_BYTES);
        } else {
            req.control.request.len = static_cast<uint32_t>(bytes - rd_bytes);
        }
 
        txoff = write16(tx_buf_, 0, req.offset);
        txoff = write32(tx_buf_, txoff, req.control.word);
        txoff = write32(tx_buf_, txoff, req.address);
 
        txoff = itransport_->sendData(tx_buf_, txoff);
        if (txoff == -1) {
            RISCV_error("Data sending error", NULL);
            rd_bytes = TAP_ERROR;
            break;
        }
 
        dbgRdTRansactionCnt_++;
        rxoff = itransport_->readData(rx_buf_, sizeof(rx_buf_));
        if (rxoff == -1) {
            RISCV_error("Data receiving error", NULL);
            rd_bytes = TAP_ERROR;
            break;
        } 
        if (rxoff == 0) {
            RISCV_error("No response. Break read transaction[%d] at %08x",
                        dbgRdTRansactionCnt_, req.address);
            rd_bytes = TAP_ERROR;
            break;
        }
 
        rsp.control.word = read32(&rx_buf_[2]);
 
        const char *NAK[2] = {"ACK", "NAK"};
        RISCV_debug("EDCL read: %s[%d], len = %d", 
                    NAK[rsp.control.response.nak],
                    rsp.control.response.seqidx,
                    rsp.control.response.len);
 
        // Retry with new sequence counter.
        if (rsp.control.response.nak) {
            RISCV_info("Sequence counter detected %d. Re-sending transaction.",
                         rsp.control.response.seqidx);
            seq_cnt_.make_uint64(rsp.control.response.seqidx);
            continue;
        }
 
        // Try to receive next packet:
        if (rsp.control.response.seqidx != seq_cnt_.to_uint32()) {
            RISCV_error("Wrong ID received %d != %d. Try again.",
                        seq_cnt_.to_uint32(), rsp.control.response.seqidx);
 
            rxoff = itransport_->readData(rx_buf_, sizeof(rx_buf_));
            if (rxoff <= 0) {
                rd_bytes = TAP_ERROR;
                break;
            }
            rsp.control.word = read32(&rx_buf_[2]);
            if (rsp.control.response.seqidx != seq_cnt_.to_uint32()) {
                rd_bytes = TAP_ERROR;
                break;
            }
        }
 
        memcpy(&obuf[rd_bytes], &rx_buf_[10], rsp.control.response.len);
        rd_bytes += rsp.control.response.len;
        seq_cnt_.make_uint64((seq_cnt_.to_uint64() + 1) & 0x3FFF);
    }
    return rd_bytes;
}
 
int EdclService::write(uint64_t addr, int bytes, uint8_t *ibuf) {
    int off;
    UdpEdclCommonType req = {0};
    UdpEdclCommonType rsp;
 
    if (!itransport_) {
        RISCV_error("UDP transport not defined, addr=%x", addr);
        return TAP_ERROR;
    }
 
    int wr_bytes = 0;
    while (wr_bytes < bytes && wr_bytes != -1) {
        req.control.request.seqidx = 
                    static_cast<uint32_t>(seq_cnt_.to_uint64());
        req.control.request.write = 1;
        req.address = static_cast<uint32_t>(addr + wr_bytes);
        if ((bytes - wr_bytes) > EDCL_PAYLOAD_MAX_BYTES) {
            req.control.request.len = 
                    static_cast<uint32_t>(EDCL_PAYLOAD_MAX_BYTES);
        } else {
            req.control.request.len = static_cast<uint32_t>(bytes - wr_bytes);
        }
 
        off = write16(tx_buf_, 0, req.offset);
        off = write32(tx_buf_, off, req.control.word);
        off = write32(tx_buf_, off, req.address);
        memcpy(&tx_buf_[off], &ibuf[wr_bytes], req.control.request.len);
 
 
        off = itransport_->sendData(tx_buf_, off + req.control.request.len);
        if (off == -1) {
            RISCV_error("Data sending error", NULL);
            wr_bytes = -1;
            break;
        }
 
        off = itransport_->readData(rx_buf_, sizeof(rx_buf_));
        if (off == -1) {
            RISCV_error("Data receiving error", NULL);
            wr_bytes = -1;
            break;
        } 
        if (off == 0) {
            RISCV_error("No response. Break write transaction.", NULL);
            wr_bytes = -1;
            break;
        }
 
        rsp.control.word = read32(&rx_buf_[2]);
 
        // Warning:
        //   response length = 0;
        const char *NAK[2] = {"ACK", "NAK"};
        RISCV_debug("EDCL write: %s[%d], len = %d", 
                    NAK[rsp.control.response.nak],
                    rsp.control.response.seqidx,
                    req.control.request.len);
 
        // Retry with new sequence counter.
        if (rsp.control.response.nak) {
            RISCV_info("Sequence counter detected %d. Re-sending transaction.",
                         rsp.control.response.seqidx);
            seq_cnt_.make_uint64(rsp.control.response.seqidx);
            continue;
        }
 
        wr_bytes += req.control.request.len;
        seq_cnt_.make_uint64(seq_cnt_.to_uint64() + 1);
    }
    return wr_bytes;
}
 
int EdclService::write16(uint8_t *buf, int off, uint16_t v) {
    buf[off++] = (uint8_t)((v >> 8) & 0xFF);
    buf[off++] = (uint8_t)(v & 0xFF);
    return off;
}
 
int EdclService::write32(uint8_t *buf, int off, uint32_t v) {
    buf[off++] = (uint8_t)((v >> 24) & 0xFF);
    buf[off++] = (uint8_t)((v >> 16) & 0xFF);
    buf[off++] = (uint8_t)((v >> 8) & 0xFF);
    buf[off++] = (uint8_t)(v & 0xFF);
    return off;
}
 
uint32_t EdclService::read32(uint8_t *buf) {
    return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3] << 0);
}
 
}  // namespace debugger
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.