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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [libdbg64g/] [services/] [exec/] [cmd/] [cmd_loadsrec.cpp] - Rev 5

Compare with Previous | Blame | View Log

/**
 * @file
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
 * @brief      SREC-file loader command.
 */
 
#include "iservice.h"
#include "cmd_loadsrec.h"
#include <iostream>
 
namespace debugger {
 
//#define SHOW_USAGE_INFO
 
#ifdef SHOW_USAGE_INFO
#define ADDR_SPACE  (1 << 16)
char mark_[ADDR_SPACE] = {0};
 
void mark_addr(uint64_t addr, int len) {
    for (int i = 0; i < len; i++) {
        if ((addr + i) >= ADDR_SPACE) {
            continue;
        }
        mark_[addr + i] = 1;
    }
}
 
bool is_flash(unsigned addr) {
    if (addr >= 0x0450 && addr < 0x0500) {
        return true;
    }
    if (addr >= 0x0580 && addr < 0x0600) {
        return true;
    }
    if (addr >= 0x0E00 && addr < 0xfe00) {
        return true;
    }
    return false;
}
 
void print_flash_usage() {
    unsigned start_addr = 0;
    int cnt = 0;
    int total_cnt = 0;
 
    RISCV_printf(NULL, 0, "!!! Free Flash regions:", NULL);
    for (unsigned i = 0; i < ADDR_SPACE; i++) {
        if (!is_flash(i)) {
            if (cnt != 0) {
                RISCV_printf(NULL, 0, "    [%04x..%04x], length %d B",
                            start_addr, (start_addr + cnt - 1), cnt);
                total_cnt += cnt;
                cnt = 0;
            }
            continue;
        }
 
        if (mark_[i]) {
            if (cnt != 0) {
                RISCV_printf(NULL, 0, "    [%04x..%04x], length %d B",
                            start_addr, (start_addr + cnt - 1), cnt);
                total_cnt += cnt;
                cnt = 0;
            }
            continue;
        }
        if (cnt == 0) {
            start_addr = i;
        }
        cnt++;
    }
 
    RISCV_printf(NULL, 0, "    =========================", NULL);
    RISCV_printf(NULL, 0, "    Total: %d B", total_cnt);
}
#endif
 
CmdLoadSrec::CmdLoadSrec(ITap *tap, ISocInfo *info) 
    : ICommand ("loadsrec", tap, info) {
 
    briefDescr_.make_string("Load SREC-file");
    detailedDescr_.make_string(
        "Description:\n"
        "    Load SREC-file to SOC target memory.\n"
        "Example:\n"
        "    loadsrec /home/hc08/image.s19\n");
}
 
bool CmdLoadSrec::isValid(AttributeType *args) {
    if ((*args)[0u].is_equal("loadsrec") 
        && (args->size() == 2 || args->size() == 3)) {
        return CMD_VALID;
    }
    return CMD_INVALID;
}
 
void CmdLoadSrec::exec(AttributeType *args, AttributeType *res) {
    res->make_nil();
    if (!isValid(args)) {
        generateError(res, "Wrong argument list");
        return;
    }
 
    const char *filename = (*args)[1].to_string();
    FILE *fp = fopen(filename, "rb");
    if (!fp) {
        generateError(res, "File not found");
        return;
    }
    fseek(fp, 0, SEEK_END);
    int sz = ftell(fp);
    rewind(fp);
    uint8_t *image = new uint8_t[sz];
    fread(image, 1, sz, fp);
    fclose(fp);
 
    int off = check_header(image);
 
    DsuMapType *dsu = info_->getpDsu();
    uint64_t soft_reset = 1;
    uint64_t addr = reinterpret_cast<uint64_t>(&dsu->ulocal.v.soft_reset);
    tap_->write(addr, 8, reinterpret_cast<uint8_t *>(&soft_reset));
 
    uint64_t sec_addr;
    int sec_sz;
    uint8_t sec_data[1024];
    while ((off = readline(image, off, sec_addr, sec_sz, sec_data)) != 0) {
        tap_->write(sec_addr, sec_sz, sec_data);
#ifdef SHOW_USAGE_INFO
        mark_addr(sec_addr, sec_sz);
#endif
    }
 
//    soft_reset = 0;
//    tap_->write(addr, 8, reinterpret_cast<uint8_t *>(&soft_reset));
    delete [] image;
 
#ifdef SHOW_USAGE_INFO
    print_flash_usage();
#endif
}
 
uint8_t CmdLoadSrec::str2byte(uint8_t *pair) {
    uint8_t ret = 0;
    for (int i = 0; i < 2; i++) {
        ret <<= 4;
        if (pair[i] >= '0' && pair[i] <= '9') {
            ret |= pair[i] - '0';
        } else if (pair[i] >= 'A' && pair[i] <= 'F') {
            ret |= pair[i] - 'A' + 10;
        } else if (pair[i] >= 'a' && pair[i] <= 'f') {
            ret |= pair[i] - 'a' + 10;
        }
    }
    return ret;
}
 
bool CmdLoadSrec::check_crc(uint8_t *str, int sz) {
    uint8_t sum = 0;
    uint8_t *cur = str;
    for (int i = 0; i < sz; i++) {
        sum += str2byte(cur);
        cur += 2;
    }
    sum = ~sum;
    uint8_t ctrl = str2byte(cur);
    return ctrl == sum;
}
 
int CmdLoadSrec::check_header(uint8_t *img) {
    int off = 2;
    if (img[0] != 'S' || img[1] != '0') {
        return 0;
    }
    uint8_t sz = str2byte(&img[off]);
    if (!check_crc(&img[off], sz)) {
        return 0;
    }
 
    off += 2;
    uint16_t addr = str2byte(&img[off]);
    off += 2;
    addr = (addr << 8) + str2byte(&img[off]);
    off += 2;
    if (addr != 0) {
        return 0;
    }
    for (int i = 0; i < sz - 3; i++) {  // size (1) + addr (2) = 3
        header_data_[i] = static_cast<char>(str2byte(&img[off]));
        header_data_[i + 1] = 0;
        off += 2;
    }
    off += 2;  // skip checksum
    if (img[off] != '\r' || img[off + 1] != '\n') {
        return 0;
    }
    return off + 2;
}
 
int CmdLoadSrec::readline(uint8_t *img, int off,
                          uint64_t &addr, int &sz, uint8_t *out) {
    if (img[off++] != 'S') {
        return 0;
    }
    int bytes4addr = 0;
    switch (img[off++]) {    // 16-bits address only
    case '1':
        bytes4addr = 2; // 16-bits address
        break;
    case '2':
        bytes4addr = 3; // 24-bits address
        break;
    case '3':
        bytes4addr = 4; // 32-bits address
        break;
    default:
        return 0;
    }
    sz = str2byte(&img[off]);
    if (!check_crc(&img[off], sz)) {
        return 0;
    }
    sz -= 1;
    off += 2;
 
    addr = 0;
    for (int i = 0; i < bytes4addr; i++) {
        addr <<= 8;
        addr += str2byte(&img[off]);
        off += 2;
        sz--;
    }
#if 1
    // MCU specific endcoding:
    if (bytes4addr == 3) {
        uint64_t page = addr >> 16;
        addr = (0x4000 * page) + (addr & 0x3FFF);
    }
#endif
 
    for (int i = 0; i < sz; i++) {
        out[i] = static_cast<char>(str2byte(&img[off]));
        off += 2;
    }
    off += 2;  // skip checksum
    if (img[off] != '\r' || img[off + 1] != '\n') {
        return 0;
    }
    return off + 2;
}
 
}  // 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.