Line 1... |
Line 1... |
/**
|
/*
|
* @file
|
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
|
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
|
*
|
* @author Sergey Khabarov - sergeykhbr@gmail.com
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* @brief UART functional model.
|
* 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 "api_core.h"
|
#include "api_core.h"
|
#include "uart.h"
|
#include "uart.h"
|
|
|
Line 22... |
Line 31... |
|
|
|
|
UART::UART(const char *name) : IService(name) {
|
UART::UART(const char *name) : IService(name) {
|
registerInterface(static_cast<IMemoryOperation *>(this));
|
registerInterface(static_cast<IMemoryOperation *>(this));
|
registerInterface(static_cast<ISerial *>(this));
|
registerInterface(static_cast<ISerial *>(this));
|
registerAttribute("BaseAddress", &baseAddress_);
|
|
registerAttribute("Length", &length_);
|
|
registerAttribute("IrqLine", &irqLine_);
|
|
registerAttribute("IrqControl", &irqctrl_);
|
registerAttribute("IrqControl", &irqctrl_);
|
|
registerAttribute("AutoTestEna", &autoTestEna_);
|
|
registerAttribute("TestCases", &testCases_);
|
|
|
baseAddress_.make_uint64(0);
|
|
length_.make_uint64(0);
|
|
irqLine_.make_uint64(0);
|
|
irqctrl_.make_string("");
|
|
listeners_.make_list(0);
|
listeners_.make_list(0);
|
RISCV_mutex_init(&mutexListeners_);
|
RISCV_mutex_init(&mutexListeners_);
|
|
|
memset(®s_, 0, sizeof(regs_));
|
memset(®s_, 0, sizeof(regs_));
|
regs_.status = UART_STATUS_TX_EMPTY | UART_STATUS_RX_EMPTY;
|
regs_.status = UART_STATUS_TX_EMPTY | UART_STATUS_RX_EMPTY;
|
|
|
p_rx_wr_ = rxfifo_;
|
p_rx_wr_ = rxfifo_;
|
p_rx_rd_ = rxfifo_;
|
p_rx_rd_ = rxfifo_;
|
rx_total_ = 0;
|
rx_total_ = 0;
|
|
pautotest_ = NULL;
|
}
|
}
|
|
|
UART::~UART() {
|
UART::~UART() {
|
RISCV_mutex_destroy(&mutexListeners_);
|
RISCV_mutex_destroy(&mutexListeners_);
|
|
if (pautotest_) {
|
|
delete pautotest_;
|
|
}
|
}
|
}
|
|
|
void UART::postinitService() {
|
void UART::postinitService() {
|
iwire_ = static_cast<IWire *>(
|
iwire_ = static_cast<IWire *>(
|
RISCV_get_service_iface(irqctrl_.to_string(), IFACE_WIRE));
|
RISCV_get_service_port_iface(irqctrl_[0u].to_string(),
|
|
irqctrl_[1].to_string(),
|
|
IFACE_WIRE));
|
if (!iwire_) {
|
if (!iwire_) {
|
RISCV_error("Can't find IWire interface %s", irqctrl_.to_string());
|
RISCV_error("Can't find IWire interface %s", irqctrl_[0u].to_string());
|
|
}
|
|
if (autoTestEna_.to_bool()) {
|
|
pautotest_ = new AutoTest(static_cast<ISerial *>(this), &testCases_);
|
}
|
}
|
}
|
}
|
|
|
int UART::writeData(const char *buf, int sz) {
|
int UART::writeData(const char *buf, int sz) {
|
if (sz > (RX_FIFO_SIZE - rx_total_)) {
|
if (sz > (RX_FIFO_SIZE - rx_total_)) {
|
Line 67... |
Line 80... |
p_rx_wr_ = rxfifo_;
|
p_rx_wr_ = rxfifo_;
|
}
|
}
|
}
|
}
|
|
|
if (regs_.status & UART_CONTROL_RX_IRQ_ENA) {
|
if (regs_.status & UART_CONTROL_RX_IRQ_ENA) {
|
iwire_->raiseLine(irqLine_.to_int());
|
iwire_->raiseLine();
|
}
|
}
|
return sz;
|
return sz;
|
}
|
}
|
|
|
void UART::registerRawListener(IFace *listener) {
|
void UART::registerRawListener(IFace *listener) {
|
Line 91... |
Line 104... |
break;
|
break;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
void UART::b_transport(Axi4TransactionType *trans) {
|
void UART::getListOfPorts(AttributeType *list) {
|
|
list->make_list(0);
|
|
}
|
|
|
|
int UART::openPort(const char *port, AttributeType settings) {
|
|
return 0;
|
|
}
|
|
|
|
void UART::closePort() {
|
|
}
|
|
|
|
|
|
ETransStatus UART::b_transport(Axi4TransactionType *trans) {
|
uint64_t mask = (length_.to_uint64() - 1);
|
uint64_t mask = (length_.to_uint64() - 1);
|
uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4;
|
uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4;
|
char wrdata;
|
char wrdata;
|
trans->response = MemResp_Valid;
|
trans->response = MemResp_Valid;
|
if (trans->action == MemAction_Write) {
|
if (trans->action == MemAction_Write) {
|
Line 163... |
Line 188... |
default:
|
default:
|
trans->rpayload.b32[i] = ~0;
|
trans->rpayload.b32[i] = ~0;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
return TRANS_OK;
|
|
}
|
|
|
|
/**
|
|
* CPU validation purpose. Reaction on keyboard interrupt:
|
|
*/
|
|
|
|
UART::AutoTest::AutoTest(ISerial *parent, AttributeType *tests) {
|
|
parent_ = parent;
|
|
tests_ = *tests;
|
|
testcnt_ = 0;
|
|
IClock *iclk = static_cast<IClock *>(
|
|
RISCV_get_service_iface("core0", IFACE_CLOCK));
|
|
if (iclk && tests_.is_list() && tests_.size()) {
|
|
const AttributeType &t0 = tests_[testcnt_];
|
|
if (t0.size() == 2) {
|
|
iclk->registerStepCallback(static_cast<IClockListener *>(this),
|
|
t0[0u].to_uint64());
|
|
}
|
|
}
|
|
}
|
|
|
|
void UART::AutoTest::stepCallback(uint64_t t) {
|
|
const AttributeType &tn = tests_[testcnt_];
|
|
char msg[64];
|
|
int msglen = 0;
|
|
const char *pbuf = tn[1].to_string();
|
|
for (unsigned i = 0; i < tn[1].size(); i++) {
|
|
if (pbuf[i] == '\\' && pbuf[i+1] == 'r') {
|
|
++i;
|
|
msg[msglen++] = '\r';
|
|
msg[msglen] = '\0';
|
|
continue;
|
|
} else if (pbuf[i] == '\\' && pbuf[i+1] == 'n') {
|
|
++i;
|
|
msg[msglen++] = '\n';
|
|
msg[msglen] = '\0';
|
|
continue;
|
|
}
|
|
msg[msglen++] = pbuf[i];
|
|
msg[msglen] = '\0';
|
|
}
|
|
parent_->writeData(msg, msglen);
|
|
|
|
if (++testcnt_ < tests_.size()) {
|
|
const AttributeType &t0 = tests_[testcnt_];
|
|
IClock *iclk = static_cast<IClock *>(
|
|
RISCV_get_service_iface("core0", IFACE_CLOCK));
|
|
iclk->registerStepCallback(static_cast<IClockListener *>(this),
|
|
t0[0u].to_uint64());
|
|
}
|
}
|
}
|
|
|
} // namespace debugger
|
} // namespace debugger
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|