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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [libdbg64g/] [services/] [debug/] [serial_dbglink.cpp] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 sergeykhbr
/*
2
 *  Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
3
 *
4
 *  Licensed under the Apache License, Version 2.0 (the "License");
5
 *  you may not use this file except in compliance with the License.
6
 *  You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 *  Unless required by applicable law or agreed to in writing, software
11
 *  distributed under the License is distributed on an "AS IS" BASIS,
12
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *  See the License for the specific language governing permissions and
14
 *  limitations under the License.
15
 *
16
 * @details
17
 *             Write command:
18
 *                 Send     [11.Length-1].Addr[63:0].Data[31:0]*(x Length)
19
 *             Read command:
20
 *                 Send     [10.Length-1].Addr[63:0]
21
 *                 Receive  Data[31:0]*(x Length)
22
 */
23
 
24
#include "api_core.h"
25
#include "serial_dbglink.h"
26
 
27
namespace debugger {
28
 
29
/** Class registration in the Core */
30
REGISTER_CLASS(SerialDbgService)
31
 
32
SerialDbgService::SerialDbgService(const char *name)
33
    : IService(name) {
34
    registerInterface(static_cast<ITap *>(this));
35
    registerAttribute("Timeout", &timeout_);
36
    registerAttribute("Port", &port_);
37
 
38
    RISCV_event_create(&event_block_, "SerialDbg_event_block");
39
}
40
 
41
SerialDbgService::~SerialDbgService() {
42
    RISCV_event_close(&event_block_);
43
}
44
 
45
void SerialDbgService::postinitService() {
46
    iserial_ = static_cast<ISerial *>(
47
        RISCV_get_service_iface(port_.to_string(), IFACE_SERIAL));
48
    if (!iserial_) {
49
        RISCV_error("Can't find ISerial interface %s", port_.to_string());
50
        return;
51
    }
52
    iserial_->registerRawListener(static_cast<IRawListener *>(this));
53
#if 1  // hardcoded scale in tapuart, no need in clock detection
54
    /** Automatic baudrate definition on hardware side:
55
     *    [0] 0x55 - to init baud rate detector
56
     *    [1] 0x55 - to confirm baud rate value.
57
     */
58
    char tbuf[5] = {0x55, 0x55, 0x55, 0x55};
59
    iserial_->writeData(tbuf, 4);
60
#endif
61
}
62
 
63
void SerialDbgService::predeleteService() {
64
    if (iserial_) {
65
        iserial_->unregisterRawListener(static_cast<IRawListener *>(this));
66
    }
67
}
68
 
69
int SerialDbgService::read(uint64_t addr, int bytes, uint8_t *obuf) {
70
    if (!iserial_) {
71
        return TAP_ERROR;
72
    }
73
    if (bytes <= 0 || (bytes & 0x3) != 0) {
74
        RISCV_error("Unaligned read %d", bytes);
75
        return TAP_ERROR;
76
    }
77
    addr &= 0xFFFFFFFFull;
78
    int bytes_to_read = bytes;
79
    uint8_t *tout = obuf;
80
    pkt_.fields.magic = MAGIC_ID;
81
    pkt_.fields.addr = addr;
82
    while (bytes_to_read) {
83
        pkt_.fields.cmd = (0x2 << 6);
84
        if (bytes_to_read > 4 * UART_MST_BURST_MAX) {
85
            req_count_ = 4 * UART_MST_BURST_MAX;
86
            pkt_.fields.cmd |= 0x3F;
87
        } else {
88
            req_count_ = bytes_to_read;
89
            pkt_.fields.cmd |= ((bytes_to_read / 4) - 1) & 0x3F;
90
        }
91
        rd_count_ = 0;
92
        wait_bytes_ = req_count_;
93
        RISCV_event_clear(&event_block_);
94
        iserial_->writeData(pkt_.buf, UART_REQ_HEADER_SZ);
95
 
96
        if (RISCV_event_wait_ms(&event_block_, timeout_.to_int()) != 0) {
97
            RISCV_error("Reading [%08" RV_PRI64 "x] failed", addr);
98
            return TAP_ERROR;
99
        }
100
        if (rd_count_ != req_count_) {
101
            RISCV_error("Read bytes %d of %d", rd_count_, req_count_);
102
            return TAP_ERROR;
103
        }
104
 
105
        memcpy(tout, rxbuf_[0].buf, rd_count_);
106
        tout += rd_count_;
107
        pkt_.fields.addr += static_cast<unsigned>(rd_count_);
108
        bytes_to_read -= rd_count_;
109
    }
110
    return bytes;
111
}
112
 
113
int SerialDbgService::write(uint64_t addr, int bytes, uint8_t *ibuf) {
114
    if (!iserial_) {
115
        return TAP_ERROR;
116
    }
117
    if (bytes <= 0 || (bytes & 0x3) != 0) {
118
        RISCV_error("Unaligned write %d", bytes);
119
        return TAP_ERROR;
120
    }
121
    addr &= 0xFFFFFFFFull;
122
    int bytes_to_write = bytes;
123
    uint8_t *tin = ibuf;
124
    pkt_.fields.magic = MAGIC_ID;
125
    pkt_.fields.addr = addr;
126
    while (bytes_to_write) {
127
        pkt_.fields.cmd = (0x3 << 6);
128
        if (bytes_to_write > 4 * UART_MST_BURST_MAX) {
129
            req_count_ = 4 * UART_MST_BURST_MAX;
130
            pkt_.fields.cmd |= 0x3F;
131
        } else {
132
            req_count_ = bytes_to_write;
133
            pkt_.fields.cmd |= ((bytes_to_write / 4) - 1) & 0x3F;
134
        }
135
        memcpy(pkt_.fields.data, tin, req_count_);
136
 
137
        wait_bytes_ = 4;
138
        rd_count_ = 0;
139
        RISCV_event_clear(&event_block_);
140
        iserial_->writeData(pkt_.buf, UART_REQ_HEADER_SZ + req_count_);
141
 
142
        // Waiting "ACK\n" handshake
143
        if (RISCV_event_wait_ms(&event_block_, timeout_.to_int()) != 0) {
144
            RISCV_error("Writing [%08" RV_PRI64 "x] failed", addr);
145
            return TAP_ERROR;
146
        }
147
 
148
        tin += req_count_;
149
        bytes_to_write -= req_count_;
150
        pkt_.fields.addr += static_cast<unsigned>(req_count_);
151
    }
152
    return bytes;
153
}
154
 
155
void SerialDbgService::updateData(const char *buf, int buflen) {
156
    uint8_t *tbuf = &rxbuf_[0].buf[rd_count_];
157
    memcpy(tbuf, buf, buflen);
158
    rd_count_ += buflen;
159
    if (rd_count_ < wait_bytes_) {
160
        return;
161
    }
162
    RISCV_event_set(&event_block_);
163
}
164
 
165
}  // namespace debugger

powered by: WebSVN 2.1.0

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