You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARMv7 CPUlator中JTAG UART非括号字符FIFO回显失败问题

ARMv7 CPUlator下JTAG UART回显异常:字符已读取但无法回显

在ARMv7 CPUlator环境中,尝试将JTAG UART接口输入的非双引号字符从Read FIFO回显至Write FIFO时遇到问题:字符已被Read FIFO读取,但无法完成回显。以下是原汇编代码:

.section .text
.global _start
 
.equ UART_BASE, 0xFF201000
.equ READ_FIFO_OFFSET, 0x00
.equ WRITE_FIFO_OFFSET, 0x04
.equ NUM_CHARS_TO_READ, 16   // Adjust based on your system
 
_start:
    // Infinite loop
    B loop
 
loop:
    // Read characters from the UART Read FIFO
    LDR R1, =UART_BASE
    LDR R2, =READ_FIFO_OFFSET
    LDR R3, =NUM_CHARS_TO_READ
read_loop:
    LDRB R0, [R1, R2]  // Read a character from the Read FIFO
    CMP R0, #0      // Check if the character is null (end of string)
    BEQ loop_end
 
    // Check if the character is a double quote (ASCII 0x22)
    CMP R0, #0x22
    BNE check_next_char
 
    // Start echoing characters until the next double quote
    B echo_chars
 
check_next_char:
    // Increment the offset for the next character in the loop
    ADD R2, R2, #1
    SUBS R3, R3, #1 // Decrement the character count
    BNE read_loop   // Continue reading if there are more characters
 
loop_end:
    // Retry reading from the UART (you might want to add a delay here)
    B loop
 
echo_chars:
    // Echo characters to the Write FIFO until the next double quote
    LDR R2, =WRITE_FIFO_OFFSET
echo_loop:
    STRB R0, [R1, R2]  // Echo the character to the Write FIFO
    ADD R2, R2, #1
    CMP R0, #0x22   // Check if the echoed character is a double quote
    BEQ loop        // If double quote, go back to reading
 
    // Increment to the next character in the loop
    ADD R2, R2, #1
    SUBS R3, R3, #1
    CMP R3, #0
    BNE read_loop   // Continue reading if there are more characters
 
    // If we reach here, we have echoed characters until the next double quote
    B loop

原代码存在几个核心逻辑错误:

  • 对JTAG UART寄存器的误解:READ_FIFO(0x00)和WRITE_FIFO(0x04)不是连续的字符存储地址,而是包含状态位的寄存器。READ_FIFO的第0位表示是否有数据可读,第8-15位是实际字符;WRITE_FIFO的第1位表示是否可以写入,第8-15位是要写入的字符。原代码直接按偏移递增读取,完全错误。
  • 回显逻辑混乱:echo_chars中重复递增R2,且跳转到read_loop的逻辑没有持续读取新输入的字符,导致回显流程中断。
  • 结束条件错误:用空字符(0)判断读取结束不符合JTAG UART的输入逻辑,输入字符不会自动带空结尾,应通过状态位判断是否有数据。

以下是修正后的代码,可实现非双引号字符的正常回显:

.section .text
.global _start

.equ UART_BASE, 0xFF201000
.equ RXFIFO_STATUS, 0x00  // 第0位:有数据可读(1=有数据),第8-15位:读取的字符
.equ TXFIFO_STATUS, 0x04  // 第1位:可写入(1=FIFO未满),第8-15位:要写入的字符
.equ CHAR_MASK, 0xFF00    // 提取字符的掩码(高8位)
.equ RXFIFO_NOT_EMPTY, 0x01  // 有数据的状态位
.equ TXFIFO_NOT_FULL, 0x02   // 可写入的状态位
.equ DOUBLE_QUOTE, 0x22      // 双引号ASCII码

_start:
    B loop  // 进入主循环

loop:
    LDR R1, =UART_BASE  // 加载UART基地址到R1

wait_for_input:
    // 等待Read FIFO中有数据
    LDR R0, [R1, #RXFIFO_STATUS]
    TST R0, #RXFIFO_NOT_EMPTY
    BEQ wait_for_input  // 无数据则等待

    // 读取字符(提取高8位)
    LDR R0, [R1, #RXFIFO_STATUS]
    AND R0, R0, #CHAR_MASK
    LSR R0, R0, #8  // 右移8位得到ASCII字符

    // 判断是否是双引号,是则跳过回显
    CMP R0, #DOUBLE_QUOTE
    BEQ loop  // 双引号直接回到等待输入

    // 回显字符:先等待Write FIFO可写入
wait_for_tx_ready:
    LDR R2, [R1, #TXFIFO_STATUS]
    TST R2, #TXFIFO_NOT_FULL
    BEQ wait_for_tx_ready  // FIFO满则等待

    // 将字符写入Write FIFO(左移8位到高8位)
    LSL R0, R0, #8
    STR R0, [R1, #TXFIFO_STATUS]

    B loop  // 回到主循环继续处理下一个字符

修正说明:

  • 正确处理UART寄存器:通过状态位判断Read FIFO是否有数据、Write FIFO是否可写入,提取高8位作为实际字符,符合JTAG UART的寄存器定义。
  • 简化回显逻辑:每个字符读取后,直接判断是否为双引号,非双引号则等待Write FIFO就绪后写入,流程清晰。
  • 去掉错误的偏移递增:不再错误地递增寄存器偏移,而是直接操作固定的状态寄存器。

内容的提问来源于stack exchange,提问作者Jared Le

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 12:14:51