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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [libdbg64g/] [services/] [comport/] [comport.cpp] - Rev 4

Compare with Previous | Blame | View Log

/*
 *  Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
 
#include <iostream>
#include <stdio.h>
#include <string.h>
#include "api_types.h"
#include "api_core.h"
#include "coreservices/iserial.h"
#include "comport.h"
 
 
namespace debugger {
 
/** Class registration in the Core */
REGISTER_CLASS(ComPortService)
 
ComPortService::ComPortService(const char *name) 
    : IService(name) {
    registerInterface(static_cast<IThread *>(this));
    registerInterface(static_cast<ISerial *>(this));
    registerInterface(static_cast<IRawListener *>(this));
    registerAttribute("Enable", &isEnable_);
    registerAttribute("UartSim", &uartSim_);
    registerAttribute("LogFile", &logFile_);
    registerAttribute("ComPortName", &comPortName_);
    registerAttribute("ComPortSpeed", &comPortSpeed_);
 
    isEnable_.make_boolean(true);
    uartSim_.make_string("");
    logFile_.make_string("uart0.log");
    logfile_ = NULL;
    comPortName_.make_string("");
    comPortSpeed_.make_int64(115200);
    portListeners_.make_list(0);
    iuartSim_ = 0;
    portOpened_ = false;
    RISCV_mutex_init(&mutexListeners_);
    prtHandler_ = 0;
}
 
ComPortService::~ComPortService() {
    RISCV_mutex_destroy(&mutexListeners_);
    if (logfile_) {
        fclose(logfile_);
        logfile_ = NULL;
    }
}
 
void ComPortService::postinitService() {
    const AttributeType *glb = RISCV_get_global_settings();
    isSimulation_ = (*glb)["SimEnable"].to_bool();
 
    if (isSimulation_) {
        iuartSim_ = static_cast<ISerial *>(
            RISCV_get_service_iface(uartSim_.to_string(), IFACE_SERIAL));
        if (!iuartSim_) {
            RISCV_error("Can't get serial interface of UART simulator",
                        uartSim_.to_string());
            return;
        } else {
            iuartSim_->registerRawListener(static_cast<IRawListener *>(this));
        }
    }
 
    if (isEnable_.to_bool()) {
        if (!run()) {
            RISCV_error("Can't create thread.", NULL);
            return;
        }
    }
 
    logfile_ = 0;
    if (logFile_.size()) {
        char tst[256];
        RISCV_sprintf(tst, sizeof(tst), "Can't open '%s' file",
                      logFile_.to_string());
        logfile_ = fopen(logFile_.to_string(), "w");
    }
}
 
void ComPortService::predeleteService() {
    if (isSimulation_ && iuartSim_) {
        iuartSim_->unregisterRawListener(static_cast<IRawListener *>(this));
    }
}
 
//#define READ_RAWDATA_FROM_FILE
void ComPortService::busyLoop() {
    char tbuf[4096];
    int tbuf_cnt;
#ifdef READ_RAWDATA_FROM_FILE
    FILE *script = fopen("e:/uart0.log", "r");
    char logbuf[1024];
    int logbuf_sz;
#endif
 
    while (isEnabled()) {
#ifdef READ_RAWDATA_FROM_FILE
        logbuf_sz = fread(logbuf, 1, sizeof(logbuf), script);
        if (logbuf_sz) {
            for (unsigned i = 0; i < portListeners_.size(); i++) {
                IRawListener *ilstn = static_cast<IRawListener *>(
                                portListeners_[i].to_iface());
                ilstn->updateData(logbuf, logbuf_sz);
            }
        } else {
            fseek(script, 0, SEEK_SET);
        }
#endif
        if (!isSimulation_ && !portOpened_) {
            AttributeType settings;
            settings.make_list(4);
            settings[0u].make_int64(comPortSpeed_.to_int());
            int err = openPort(comPortName_.to_string(), settings);
            if (err < 0) {
                RISCV_error("Openning %s at %d . . .failed",
                        comPortName_.to_string(), comPortSpeed_.to_int());
                RISCV_sleep_ms(1000);
                continue;
            } else {
                portOpened_ = true;
            }
        }
        // Sending...
        tbuf_cnt = 0;
        while (!txFifo_.isEmpty()) {
            tbuf[tbuf_cnt++] = txFifo_.get();
        }
        if (tbuf_cnt) {
            if (isSimulation_ && iuartSim_) {
                iuartSim_->writeData(tbuf, tbuf_cnt);
            } else if (!isSimulation_ && prtHandler_) {
                writeSerialPort(&prtHandler_, tbuf, tbuf_cnt);
            }
        }
 
        // Receiveing...
        if (!isSimulation_ && prtHandler_) {
            tbuf_cnt = readSerialPort(&prtHandler_, tbuf,
                                        sizeof(tbuf) - tbuf_cnt);
            if (tbuf_cnt < 0) { 
                closePort();
                portOpened_ = false;
                continue;
            }
        } else if (isSimulation_) {
            tbuf_cnt = 0;
            while (!rxFifo_.isEmpty()
                && tbuf_cnt < static_cast<int>(sizeof(tbuf) - 1)) {
                tbuf[tbuf_cnt++] = rxFifo_.get();
                tbuf[tbuf_cnt] = '\0';
            }
        }
        if (tbuf_cnt) {
            RISCV_mutex_lock(&mutexListeners_);
            for (unsigned i = 0; i < portListeners_.size(); i++) {
                IRawListener *ilstn = static_cast<IRawListener *>(
                                portListeners_[i].to_iface());
                ilstn->updateData(tbuf, tbuf_cnt);
            }
            RISCV_mutex_unlock(&mutexListeners_);
            if (logfile_) {
                fwrite(tbuf, tbuf_cnt, 1, logfile_);
                fflush(logfile_);
            }
        }
 
        RISCV_sleep_ms(50);
    }
}
 
int ComPortService::writeData(const char *buf, int sz) {
    // @todo: mutex
    for (int i = 0; i < sz; i++) {
        txFifo_.put(buf[i]);
    }
    return sz;
}
 
 
void ComPortService::registerRawListener(IFace *iface) {
    AttributeType t1(iface);
    RISCV_mutex_lock(&mutexListeners_);
    portListeners_.add_to_list(&t1);
    RISCV_mutex_unlock(&mutexListeners_);
}
 
void ComPortService::unregisterRawListener(IFace *iface) {
    RISCV_mutex_lock(&mutexListeners_);
    for (unsigned i = 0; i < portListeners_.size(); i++) {
        IFace *itmp = portListeners_[i].to_iface();
        if (itmp == iface) {
            portListeners_.remove_from_list(i);
            break;
        }
    }
    RISCV_mutex_unlock(&mutexListeners_);
}
 
void ComPortService::updateData(const char *buf, int buflen) {
    // Data from UART simulation:
    for (int i = 0; i < buflen; i++) {
        rxFifo_.put(buf[i]);
    }
}
 
}  // 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.