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
相关产品推荐
相关产品推荐

