流式读取数据

User

@5025F_gpiotest.svf 帮我实现完整的流式读取


Cursor

让我先查看SVF文件中大SDR命令的具体格式:

现在我理解了SVF文件的结构。让我实现完整的流式读取:

c 复制代码
/**
 * @file    svf_parser.c
 * @brief   SVF文件解析器(完整流式读取版)
 * @author  SVF Player Project
 * @date    2025
 * 
 * 支持任意大小的SDR命令,通过流式读取实现
 */

#include "svf_parser.h"
#include "jtag.h"
#include "delay.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

/* 调试开关 */
#define SVF_DEBUG   0

/* 解析器上下文 */
static SVF_Context svf_ctx;

/* 缓冲区定义 */
#define CMD_BUFFER_SIZE     256     /* 命令头部缓冲区 */
#define CHUNK_SIZE          64      /* 数据块大小(字节)*/
#define HEX_READ_SIZE       256     /* 每次读取的hex字符数 */

static char cmd_buffer[CMD_BUFFER_SIZE];
static char hex_buffer[HEX_READ_SIZE + 16];
static uint8_t chunk_tdi[CHUNK_SIZE];
static uint8_t chunk_tdo[CHUNK_SIZE];
static uint8_t chunk_expected[CHUNK_SIZE];
static uint8_t chunk_mask[CHUNK_SIZE];

static char error_desc[64];

/* 内部函数声明 */
static int SVF_HexCharToValue(char c);
static void SVF_SkipWhitespace(const char **str);
static int SVF_ParseNumber(const char **str, uint32_t *value);
static int SVF_ParseFloat(const char **str, float *value);
static int SVF_ParseKeyword(const char **str, char *keyword, int max_len);

/**
 * @brief  十六进制字符转数值
 */
static int SVF_HexCharToValue(char c)
{
    if (c >= '0' && c <= '9') return c - '0';
    if (c >= 'A' && c <= 'F') return c - 'A' + 10;
    if (c >= 'a' && c <= 'f') return c - 'a' + 10;
    return -1;
}

/**
 * @brief  解析十六进制字符串到字节数组(内存中的字符串)
 */
static void SVF_ParseHexToBytes(const char *hex_str, int hex_len, 
                                 uint8_t *buffer, uint32_t byte_count)
{
    memset(buffer, 0, byte_count);
    if (hex_len <= 0 || hex_str == NULL) return;
    
    int buf_idx = 0;
    int nibble_pos = 0;
    
    for (int i = hex_len - 1; i >= 0 && buf_idx < (int)byte_count; i--) {
        char c = hex_str[i];
        if (isspace((unsigned char)c)) continue;
        
        int val = SVF_HexCharToValue(c);
        if (val < 0) continue;
        
        if (nibble_pos == 0) {
            buffer[buf_idx] = (uint8_t)val;
            nibble_pos = 1;
        } else {
            buffer[buf_idx] |= (uint8_t)(val << 4);
            buf_idx++;
            nibble_pos = 0;
        }
    }
}

/**
 * @brief  从文件读取一个字符
 */
static char SVF_FileReadChar(FIL *file)
{
    char c;
    UINT br;
    if (f_read(file, &c, 1, &br) == FR_OK && br > 0) {
        return c;
    }
    return '\0';
}

/**
 * @brief  初始化SVF解析器
 */
void SVF_Parser_Init(void)
{
    memset(&svf_ctx, 0, sizeof(SVF_Context));
    svf_ctx.end_dr = TAP_IDLE;
    svf_ctx.end_ir = TAP_IDLE;
    svf_ctx.frequency = 1000000;
    error_desc[0] = '\0';
}

/**
 * @brief  在文件中搜索字符串,返回找到的位置
 */
static int SVF_SearchInFile(FIL *file, const char *target, uint32_t *found_pos)
{
    uint32_t start_pos = f_tell(file);
    int target_len = strlen(target);
    int match_idx = 0;
    char c;
    
    while ((c = SVF_FileReadChar(file)) != '\0') {
        if (toupper((unsigned char)c) == toupper((unsigned char)target[match_idx])) {
            if (match_idx == 0) {
                *found_pos = f_tell(file) - 1;
            }
            match_idx++;
            if (match_idx == target_len) {
                return 1;  /* 找到 */
            }
        } else {
            match_idx = 0;
        }
    }
    
    f_lseek(file, start_pos);
    return 0;  /* 未找到 */
}

/**
 * @brief  统计文件中两个位置之间的有效hex字符数
 */
static uint32_t SVF_CountHexChars(FIL *file, uint32_t start_pos, uint32_t end_pos)
{
    uint32_t saved_pos = f_tell(file);
    uint32_t count = 0;
    char c;
    
    f_lseek(file, start_pos);
    
    while (f_tell(file) < end_pos) {
        c = SVF_FileReadChar(file);
        if (c == '\0') break;
        if (SVF_HexCharToValue(c) >= 0) {
            count++;
        }
    }
    
    f_lseek(file, saved_pos);
    return count;
}

/**
 * @brief  从文件指定范围读取hex数据并转换为字节(流式,从末尾开始)
 * @param  file: 文件指针
 * @param  hex_start: hex数据起始位置
 * @param  hex_end: hex数据结束位置(')'的位置)
 * @param  buffer: 输出缓冲区
 * @param  byte_count: 需要读取的字节数
 * @param  byte_offset: 从第几个字节开始(从LSB端计数)
 * @return 实际读取的字节数
 */
static uint32_t SVF_ReadHexFromFile(FIL *file, uint32_t hex_start, uint32_t hex_end,
                                     uint8_t *buffer, uint32_t byte_count, uint32_t byte_offset)
{
    memset(buffer, 0, byte_count);
    
    uint32_t saved_pos = f_tell(file);
    
    /* 需要跳过的nibble数(从末尾算) */
    uint32_t skip_nibbles = byte_offset * 2;
    /* 需要读取的nibble数 */
    uint32_t need_nibbles = byte_count * 2;
    
    /* 从hex_end-1开始向前扫描 */
    uint32_t pos = hex_end - 1;
    uint32_t nibbles_skipped = 0;
    uint32_t nibbles_read = 0;
    int buf_idx = 0;
    int nibble_in_byte = 0;  /* 0=低nibble, 1=高nibble */
    
    while (pos >= hex_start && nibbles_read < need_nibbles) {
        f_lseek(file, pos);
        char c = SVF_FileReadChar(file);
        
        int val = SVF_HexCharToValue(c);
        if (val >= 0) {
            if (nibbles_skipped < skip_nibbles) {
                /* 跳过这些nibble */
                nibbles_skipped++;
            } else {
                /* 存储这个nibble */
                if (nibble_in_byte == 0) {
                    buffer[buf_idx] = (uint8_t)val;
                    nibble_in_byte = 1;
                } else {
                    buffer[buf_idx] |= (uint8_t)(val << 4);
                    buf_idx++;
                    nibble_in_byte = 0;
                }
                nibbles_read++;
            }
        }
        
        if (pos == 0) break;
        pos--;
    }
    
    f_lseek(file, saved_pos);
    
    return (nibbles_read + 1) / 2;
}

/**
 * @brief  执行大的SDR命令(真正的流式处理)
 */
static SVF_Result SVF_ExecuteLargeSDR(FIL *file, uint32_t bit_count)
{
    JTAG_Result jtag_result;
    uint32_t byte_count = (bit_count + 7) / 8;
    
    printf("SDR %lu bits (%lu bytes) streaming...\r\n", bit_count, byte_count);
    
    /* 保存当前位置 */
    uint32_t cmd_start_pos = f_tell(file);
    
    /* 搜索 TDI ( */
    uint32_t tdi_pos;
    if (!SVF_SearchInFile(file, "TDI", &tdi_pos)) {
        sprintf(error_desc, "TDI not found in SDR");
        return SVF_ERROR_SYNTAX;
    }
    
    /* 跳过 "TDI" 和空白,找到 '(' */
    f_lseek(file, tdi_pos + 3);
    char c;
    while ((c = SVF_FileReadChar(file)) != '\0') {
        if (c == '(') break;
        if (!isspace((unsigned char)c)) {
            sprintf(error_desc, "Expected '(' after TDI");
            return SVF_ERROR_SYNTAX;
        }
    }
    
    uint32_t hex_start = f_tell(file);  /* '(' 后的位置 */
    
    /* 找到匹配的 ')' */
    int paren_depth = 1;
    uint32_t hex_end = hex_start;
    while ((c = SVF_FileReadChar(file)) != '\0') {
        if (c == '(') paren_depth++;
        else if (c == ')') {
            paren_depth--;
            if (paren_depth == 0) {
                hex_end = f_tell(file) - 1;  /* ')' 的位置 */
                break;
            }
        }
    }
    
    if (paren_depth != 0) {
        sprintf(error_desc, "Unmatched parenthesis");
        return SVF_ERROR_SYNTAX;
    }
    
    /* 跳过到命令结束(分号) */
    while ((c = SVF_FileReadChar(file)) != '\0' && c != ';') {
        if (c == '\n') svf_ctx.line_number++;
    }
    
    printf("  Hex data: pos %lu - %lu\r\n", hex_start, hex_end);
    
    /* 进入DRSHIFT状态 */
    jtag_result = JTAG_GotoState(TAP_DRSHIFT);
    if (jtag_result != JTAG_OK) {
        sprintf(error_desc, "Cannot enter DRSHIFT");
        return SVF_ERROR_JTAG;
    }
    
    /* 分块处理 */
    uint32_t bits_remaining = bit_count;
    uint32_t byte_offset = 0;
    uint32_t chunk_bits = CHUNK_SIZE * 8;
    uint32_t progress_step = byte_count / 20;
    if (progress_step < 1000) progress_step = 1000;
    uint32_t last_progress = 0;
    
    while (bits_remaining > 0) {
        uint32_t this_bits = (bits_remaining > chunk_bits) ? chunk_bits : bits_remaining;
        uint32_t this_bytes = (this_bits + 7) / 8;
        uint8_t is_last = (bits_remaining <= chunk_bits);
        
        /* 从文件读取hex数据 */
        SVF_ReadHexFromFile(file, hex_start, hex_end, 
                            chunk_tdi, this_bytes, byte_offset);
        
        #if SVF_DEBUG
        if (byte_offset < 64) {
            printf("  Chunk[%lu]: ", byte_offset);
            for (int i = this_bytes - 1; i >= 0; i--) {
                printf("%02X", chunk_tdi[i]);
            }
            printf("\r\n");
        }
        #endif
        
        /* JTAG移位 */
        jtag_result = JTAG_ShiftBits(chunk_tdi, NULL, this_bits, is_last ? 1 : 0);
        if (jtag_result != JTAG_OK) {
            sprintf(error_desc, "JTAG shift error");
            return SVF_ERROR_JTAG;
        }
        
        bits_remaining -= this_bits;
        byte_offset += this_bytes;
        
        /* 进度显示 */
        if (byte_offset - last_progress >= progress_step) {
            printf("  %lu / %lu bytes (%lu%%)\r\n", 
                   byte_offset, byte_count, (byte_offset * 100) / byte_count);
            last_progress = byte_offset;
        }
    }
    
    /* 移到结束状态 */
    JTAG_GotoState(svf_ctx.end_dr);
    
    printf("  SDR complete\r\n");
    
    return SVF_OK;
}

/**
 * @brief  执行小的SIR/SDR命令
 */
static SVF_Result SVF_ExecuteSmallShift(uint32_t bit_count, const char *params, uint8_t is_ir)
{
    const char *p = params;
    uint32_t byte_count = (bit_count + 7) / 8;
    
    if (byte_count > CHUNK_SIZE) {
        sprintf(error_desc, "Data too large");
        return SVF_ERROR_BUFFER_OVERFLOW;
    }
    
    /* 初始化 */
    memset(chunk_tdi, is_ir ? 0xFF : 0x00, byte_count);
    memset(chunk_expected, 0, byte_count);
    memset(chunk_mask, 0xFF, byte_count);
    uint8_t has_tdo = 0;
    
    #if SVF_DEBUG
    printf("%s %lu bits\r\n", is_ir ? "SIR" : "SDR", bit_count);
    #endif
    
    /* 解析参数 */
    while (*p) {
        char key[8];
        SVF_SkipWhitespace(&p);
        if (!SVF_ParseKeyword(&p, key, sizeof(key))) break;
        SVF_SkipWhitespace(&p);
        
        if (*p == '(') {
            p++;
            const char *hex_start = p;
            int depth = 1;
            while (*p && depth > 0) {
                if (*p == '(') depth++;
                else if (*p == ')') depth--;
                if (depth > 0) p++;
            }
            int hex_len = p - hex_start;
            if (*p == ')') p++;
            
            uint8_t *target = NULL;
            if (strcmp(key, "TDI") == 0) {
                target = chunk_tdi;
            } else if (strcmp(key, "TDO") == 0) {
                target = chunk_expected;
                has_tdo = 1;
            } else if (strcmp(key, "MASK") == 0) {
                target = chunk_mask;
            }
            
            if (target) {
                SVF_ParseHexToBytes(hex_start, hex_len, target, byte_count);
                #if SVF_DEBUG
                printf("  %s: 0x", key);
                for (int i = byte_count - 1; i >= 0; i--) printf("%02X", target[i]);
                printf("\r\n");
                #endif
            }
        }
    }
    
    /* 执行JTAG */
    JTAG_Result jr;
    if (is_ir) {
        jr = JTAG_ShiftIR(chunk_tdi, has_tdo ? chunk_tdo : NULL, bit_count, svf_ctx.end_ir);
    } else {
        jr = JTAG_ShiftDR(chunk_tdi, has_tdo ? chunk_tdo : NULL, bit_count, svf_ctx.end_dr);
    }
    
    if (jr != JTAG_OK) {
        sprintf(error_desc, "JTAG %s error %d", is_ir ? "IR" : "DR", jr);
        return SVF_ERROR_JTAG;
    }
    
    if (has_tdo) {
        if (JTAG_CompareTDO(chunk_tdo, chunk_expected, chunk_mask, bit_count) != JTAG_OK) {
            sprintf(error_desc, "%s TDO mismatch", is_ir ? "IR" : "DR");
            return SVF_ERROR_TDO_MISMATCH;
        }
    }
    
    return SVF_OK;
}

/**
 * @brief  读取完整命令到缓冲区(用于小命令)
 */
static int SVF_ReadSmallCommand(FIL *file)
{
    int len = 0;
    char c;
    uint8_t in_comment = 0;
    uint8_t last_space = 1;
    
    while ((c = SVF_FileReadChar(file)) != '\0') {
        if (c == '\n') {
            svf_ctx.line_number++;
            if (in_comment) in_comment = 0;
        }
        
        if (c == '!') { in_comment = 1; continue; }
        if (in_comment) continue;
        
        if (c == ';') {
            cmd_buffer[len] = '\0';
            return len;
        }
        
        if (isspace((unsigned char)c)) {
            if (!last_space && len > 0 && len < CMD_BUFFER_SIZE - 1) {
                cmd_buffer[len++] = ' ';
            }
            last_space = 1;
            continue;
        }
        last_space = 0;
        
        if (len < CMD_BUFFER_SIZE - 1) {
            cmd_buffer[len++] = c;
        }
    }
    
    cmd_buffer[len] = '\0';
    return len;
}

/**
 * @brief  主解析函数
 */
SVF_Result SVF_Parse_File(FIL *file)
{
    SVF_Result result;
    
    svf_ctx.file = file;
    svf_ctx.line_number = 1;
    svf_ctx.cmd_count = 0;
    svf_ctx.sir_count = 0;
    svf_ctx.sdr_count = 0;
    
    f_lseek(file, 0);
    
    printf("=== SVF Parsing Start ===\r\n");
    
    while (1) {
        /* 保存命令开始位置 */
        uint32_t cmd_pos = f_tell(file);
        
        /* 读取命令头部(判断命令类型和大小) */
        int len = SVF_ReadSmallCommand(file);
        if (len == 0 && f_eof(file)) break;
        if (len == 0) continue;
        
        const char *p = cmd_buffer;
        char keyword[16];
        
        SVF_SkipWhitespace(&p);
        if (!SVF_ParseKeyword(&p, keyword, sizeof(keyword))) continue;
        
        /* SDR 命令 */
        if (strcmp(keyword, "SDR") == 0) {
            uint32_t bit_count;
            SVF_SkipWhitespace(&p);
            if (!SVF_ParseNumber(&p, &bit_count)) continue;
            
            svf_ctx.sdr_count++;
            
            /* 判断是否为大命令 */
            uint32_t byte_count = (bit_count + 7) / 8;
            
            if (byte_count > CHUNK_SIZE) {
                /* 大命令:回退到命令开始位置,重新流式处理 */
                f_lseek(file, cmd_pos);
                
                /* 跳过 "SDR xxx" 部分 */
                char c;
                while ((c = SVF_FileReadChar(file)) != '\0') {
                    if (isdigit((unsigned char)c)) {
                        /* 跳过数字 */
                        while ((c = SVF_FileReadChar(file)) != '\0' && isdigit((unsigned char)c));
                        break;
                    }
                }
                
                result = SVF_ExecuteLargeSDR(file, bit_count);
            } else {
                result = SVF_ExecuteSmallShift(bit_count, p, 0);
            }
            
            if (result != SVF_OK) {
                printf("Error line %lu: %s\r\n", svf_ctx.line_number, error_desc);
                return result;
            }
        }
        /* SIR 命令 */
        else if (strcmp(keyword, "SIR") == 0) {
            uint32_t bit_count;
            SVF_SkipWhitespace(&p);
            if (!SVF_ParseNumber(&p, &bit_count)) continue;
            
            svf_ctx.sir_count++;
            
            result = SVF_ExecuteSmallShift(bit_count, p, 1);
            if (result != SVF_OK) {
                printf("Error line %lu: %s\r\n", svf_ctx.line_number, error_desc);
                return result;
            }
        }
        /* RUNTEST 命令 */
        else if (strcmp(keyword, "RUNTEST") == 0) {
            uint32_t tck_count = 0;
            float sec_time = 0;
            JTAG_TapState run_state = TAP_IDLE;
            
            while (*p) {
                char key[16];
                SVF_SkipWhitespace(&p);
                if (!SVF_ParseKeyword(&p, key, sizeof(key))) break;
                
                if (strcmp(key, "IDLE") == 0) { run_state = TAP_IDLE; continue; }
                if (strcmp(key, "RESET") == 0) { run_state = TAP_RESET; continue; }
                if (strcmp(key, "DRPAUSE") == 0) { run_state = TAP_DRPAUSE; continue; }
                if (strcmp(key, "IRPAUSE") == 0) { run_state = TAP_IRPAUSE; continue; }
                
                char *endptr;
                float fval = strtof(key, &endptr);
                if (endptr != key) {
                    SVF_SkipWhitespace(&p);
                    char unit[8];
                    if (SVF_ParseKeyword(&p, unit, sizeof(unit))) {
                        if (strcmp(unit, "TCK") == 0) tck_count = (uint32_t)fval;
                        else if (strcmp(unit, "SEC") == 0) sec_time = fval;
                        else if (strcmp(unit, "MS") == 0) sec_time = fval / 1000.0f;
                        else if (strcmp(unit, "US") == 0) sec_time = fval / 1000000.0f;
                    }
                }
            }
            
            JTAG_GotoState(run_state);
            if (tck_count > 0) JTAG_RunTest(tck_count);
            if (sec_time > 0) JTAG_Wait(sec_time);
        }
        /* STATE 命令 */
        else if (strcmp(keyword, "STATE") == 0) {
            while (*p) {
                char state_name[16];
                SVF_SkipWhitespace(&p);
                if (!SVF_ParseKeyword(&p, state_name, sizeof(state_name))) break;
                JTAG_GotoState(JTAG_StateFromName(state_name));
            }
        }
        /* FREQUENCY 命令 */
        else if (strcmp(keyword, "FREQUENCY") == 0) {
            float freq;
            SVF_SkipWhitespace(&p);
            if (SVF_ParseFloat(&p, &freq)) {
                char unit[8];
                SVF_SkipWhitespace(&p);
                if (SVF_ParseKeyword(&p, unit, sizeof(unit))) {
                    if (strcmp(unit, "HZ") == 0) svf_ctx.frequency = (uint32_t)freq;
                    else if (strcmp(unit, "KHZ") == 0) svf_ctx.frequency = (uint32_t)(freq * 1000);
                    else if (strcmp(unit, "MHZ") == 0) svf_ctx.frequency = (uint32_t)(freq * 1000000);
                } else {
                    svf_ctx.frequency = (uint32_t)freq;
                }
                JTAG_SetFrequency(svf_ctx.frequency);
                printf("Freq: %lu Hz\r\n", svf_ctx.frequency);
            }
        }
        /* ENDDR/ENDIR */
        else if (strcmp(keyword, "ENDDR") == 0) {
            char state[16];
            SVF_SkipWhitespace(&p);
            if (SVF_ParseKeyword(&p, state, sizeof(state))) {
                svf_ctx.end_dr = JTAG_StateFromName(state);
            }
        }
        else if (strcmp(keyword, "ENDIR") == 0) {
            char state[16];
            SVF_SkipWhitespace(&p);
            if (SVF_ParseKeyword(&p, state, sizeof(state))) {
                svf_ctx.end_ir = JTAG_StateFromName(state);
            }
        }
        /* HDR/HIR/TDR/TIR */
        else if (strcmp(keyword, "HDR") == 0) {
            SVF_SkipWhitespace(&p);
            SVF_ParseNumber(&p, &svf_ctx.hdr_length);
        }
        else if (strcmp(keyword, "HIR") == 0) {
            SVF_SkipWhitespace(&p);
            SVF_ParseNumber(&p, &svf_ctx.hir_length);
        }
        else if (strcmp(keyword, "TDR") == 0) {
            SVF_SkipWhitespace(&p);
            SVF_ParseNumber(&p, &svf_ctx.tdr_length);
        }
        else if (strcmp(keyword, "TIR") == 0) {
            SVF_SkipWhitespace(&p);
            SVF_ParseNumber(&p, &svf_ctx.tir_length);
        }
        
        svf_ctx.cmd_count++;
        
        if (svf_ctx.cmd_count % 20 == 0) {
            printf("Cmds: %lu\r\n", svf_ctx.cmd_count);
        }
    }
    
    printf("=== SVF Complete ===\r\n");
    printf("Total: %lu cmds (SIR:%lu SDR:%lu)\r\n",
           svf_ctx.cmd_count, svf_ctx.sir_count, svf_ctx.sdr_count);
    
    return SVF_OK;
}

/* 辅助函数 */
static void SVF_SkipWhitespace(const char **str)
{
    while (**str && isspace((unsigned char)**str)) (*str)++;
}

static int SVF_ParseNumber(const char **str, uint32_t *value)
{
    const char *p = *str;
    SVF_SkipWhitespace(&p);
    char *endptr;
    *value = strtoul(p, &endptr, 10);
    if (endptr == p) return 0;
    *str = endptr;
    return 1;
}

static int SVF_ParseFloat(const char **str, float *value)
{
    const char *p = *str;
    SVF_SkipWhitespace(&p);
    char *endptr;
    *value = strtof(p, &endptr);
    if (endptr == p) return 0;
    *str = endptr;
    return 1;
}

static int SVF_ParseKeyword(const char **str, char *keyword, int max_len)
{
    const char *p = *str;
    int len = 0;
    SVF_SkipWhitespace(&p);
    
    while (*p && (isalnum((unsigned char)*p) || *p == '_')) {
        if (len < max_len - 1) {
            keyword[len++] = toupper((unsigned char)*p);
        }
        p++;
    }
    keyword[len] = '\0';
    *str = p;
    return len > 0;
}

void SVF_GetStats(uint32_t *cmd_count, uint32_t *sir_count, uint32_t *sdr_count)
{
    if (cmd_count) *cmd_count = svf_ctx.cmd_count;
    if (sir_count) *sir_count = svf_ctx.sir_count;
    if (sdr_count) *sdr_count = svf_ctx.sdr_count;
}

const char* SVF_GetLastError(void)
{
    return error_desc;
}

我已经实现了完整的流式读取。主要特点:

流式处理实现

核心函数 SVF_ReadHexFromFile()

c 复制代码
/* 从文件中读取hex数据,从末尾向前处理 */
/* 支持任意偏移量,实现分块读取 */
static uint32_t SVF_ReadHexFromFile(FIL *file, 
    uint32_t hex_start,    /* hex数据起始位置 */
    uint32_t hex_end,      /* hex数据结束位置 */
    uint8_t *buffer,       /* 输出缓冲区 */
    uint32_t byte_count,   /* 本次读取字节数 */
    uint32_t byte_offset)  /* 从第几字节开始 */

大SDR命令处理流程

  1. 定位 TDI ( 的位置
  2. 找到匹配的 ) 确定数据范围
  3. 分块处理:
    • 每次读取64字节(512位)
    • 从hex数据末尾向前读取(MSB→LSB转换)
    • 发送到JTAG
    • 显示进度

内存使用

缓冲区 大小
cmd_buffer 256字节
hex_buffer 272字节
chunk_tdi/tdo/expected/mask 4×64=256字节
总计 ~800字节

对于你的SVF文件

复制代码
SDR 4661672 TDI (FFFFFFFF0000007A...);
  • 4661672位 = 582709字节
  • 分成约9105个64字节块处理
  • 每块独立从文件读取,不需要全部加载到RAM

运行时输出示例:

复制代码
SDR 4661672 bits (582709 bytes) streaming...
  Hex data: pos 12345 - 1234567
  29000 / 582709 bytes (5%)
  58000 / 582709 bytes (10%)
  ...
  SDR complete
c 复制代码
/* 从文件中读取hex数据,从末尾向前处理 */
/* 支持任意偏移量,实现分块读取 */
static uint32_t SVF_ReadHexFromFile(FIL *file, 
    uint32_t hex_start,    /* hex数据起始位置 */
    uint32_t hex_end,      /* hex数据结束位置 */
    uint8_t *buffer,       /* 输出缓冲区 */
    uint32_t byte_count,   /* 本次读取字节数 */
    uint32_t byte_offset)  /* 从第几字节开始 */
plaintext 复制代码
SDR 4661672 TDI (FFFFFFFF0000007A...);
plaintext 复制代码
SDR 4661672 bits (582709 bytes) streaming...
  Hex data: pos 12345 - 1234567
  29000 / 582709 bytes (5%)
  58000 / 582709 bytes (10%)
  ...
  SDR complete
相关推荐
Halo_tjn2 小时前
Java Set集合知识点
java·开发语言·数据结构·windows·算法
廋到被风吹走2 小时前
【Java】JPA
java·开发语言·oracle
计算机毕设指导62 小时前
基于微信小程序的设备报修系统【源码文末联系】
java·spring boot·微信小程序·小程序·tomcat·maven·intellij-idea
没有bug.的程序员2 小时前
服务治理体系:从零到一的全景落地指南
java·开发语言·数据库·微服务·架构
毕设源码-郭学长2 小时前
【开题答辩全过程】以 基于SpringBoot的足球运动员训练计划管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
-Xie-2 小时前
Redis(十六)——底层数据结构(一)
java·数据结构·redis
小园子的小菜2 小时前
深入理解Trie树:敏感词过滤的核心原理与实现思路
算法
海南java第二人2 小时前
Spring Boot自定义注解深度解析:从入门到实战进阶
java·spring boot·后端
Tisfy2 小时前
LeetCode 2402.会议室 III:优先队列大模拟
算法·leetcode·题解·优先队列·排序·大模拟