如何在 ARM CORTEX-M3 中回显 UART 中的数据

How to echo the data in the UART in ARM CORTEX-M3

我正在等待来自 UART 的字符,然后传回 UART,我附上了 .c 文件、启动和链接器代码。我使用 Qemu 模拟 LM3S811 ARM Cortex-M3 板。但是我的 qemu 给出了以下错误。其实这是我对之前的延伸 post How to wait for characters from UART and transmit back on the UART in ARM Cortex -M3 emulated by Qemu

错误:

(qemu) qemu-system-arm: Trying to execute code outside RAM or ROM at 0xbf00e000
This usually means one of the following happened:

(1) You told QEMU to execute a kernel for the wrong machine type, and it crashed on startup (eg trying to run a raspberry pi kernel on a versatilepb QEMU machine)
(2) You didn't give QEMU a kernel or BIOS filename at all, and QEMU executed a ROM full of no-op instructions until it fell off the end
(3) Your guest kernel has a bug and crashed by jumping off into nowhere

main.c

#define  U0RBR (*((volatile unsigned char *) 0x4000C000))
#define  U0THR (*((volatile unsigned char *) 0x4000C000))
#define  U0LSR (*((volatile unsigned char *) 0x4000C004))

unsigned char UART0_RxChar(void);
void UART0_TxChar(char ch);

unsigned char UART0_RxChar(void) 
{
    while( (U0LSR & 0x01) == 0) {
        continue;
    }
    return U0RBR;
}

void UART0_TxChar(char ch) 
{
    U0THR = ch;
    while( (U0LSR & 0x40) == 0 ) {
        continue;
    }
}

int main(void)
{
    char receive;
    
    while(1) {
        receive = UART0_RxChar();
        UART0_TxChar(receive);
    }
    return 0;
}

startup.s

.global start
start:
.word 0x20001000
.word main

flash.ld

MEMORY
{
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00010000
    SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00002000
}


SECTIONS 
{
    .text : {
        *(.vectors);
        *(.text);
        etext = .;
    } > FLASH

    .rodata : {
        *(.rodata);
    } > FLASH

    .data : {
        sdata = .;
        *(.data);
        edata = .;
    } > SRAM AT > FLASH

    .bss : {
        sbss = .;
        *(.bss);
        ebss = .;
    } > SRAM
}

更新后的代码

#define  UARTDR (*((volatile unsigned int *) 0x4000C000))
#define  UARTFR (*((volatile unsigned int *) 0x4000C018))

unsigned char UART0_RxChar(void);
void UART0_TxChar(char ch);

unsigned char UART0_RxChar(void) 
{
    while( (UARTFR & 0x01) == 0);
        return UARTDR;
}

void UART0_TxChar(char ch) 
{
    UARTDR = ch;
    while ( (UARTFR & 0x40) == 0);
}

int main(void)
{
    char receive;
    
    while(1) {
        receive = UART0_RxChar();
        UART0_TxChar(receive);
    }
    while(1) continue;  
}

输出:终端不允许我在终端中输入任何内容。

unsigned char UART0_RxChar(void) 
{
    while( (UARTFR & 0x01) == 0);
        return UARTDR;
}

bit 0 被标记为保留,因此这段代码不会做任何有用的事情。

位 4 虽然说

RXFE

UART Receive FIFO Empty

The meaning of this bit depends on the state of the FEN bit in the UARTLCRH register.

If the FIFO is disabled, this bit is set when the receive holding register is empty.

If the FIFO is enabled, this bit is set when the receive FIFO is empty.

所以独立于FEN控制位。当 fifo 为空时设置第 4 位,这意味着当它从 1 变为 0 时至少已接收到一个字符。
所以

unsigned char UART0_RxChar(void) 
{
    while( (UARTFR & 0x10) != 0) continue; //while empty wait
    return UARTDR;
}

当 tx 缓冲区已满时设置位 5,这意味着没有更多空间。所以

void UART0_TxChar(char ch) 
{
    while ( (UARTFR & 0x20) != 0) continue; //while full wait
    UARTDR = ch;
}

你可以改为

void UART0_TxChar(char ch) 
{
    while ( (UARTFR & (1<<5)) != 0) continue; //while full wait
    UARTDR = ch;
}

使用 0x20 或 (1<<5) 的优缺点,显然两者是相同的。两者都提供更好的可读性和验证,具体取决于个人以及他们如何 use/read 手册等

我发现的问题是,如果您按住键盘上的键并重复进入虚拟终端,它似乎会溢出模拟的 rx 缓冲区并出现大量字符。你在真正的硬件上没有这个问题。 qemu 是开源的,所以你可以很容易地去阅读代码看看发生了什么。可能它需要更多的 accurate/correct uart 初始化,因为真实硬件上的 uart 无法使用此代码编写。需要一个 uart 初始化。

明白这绝对none与cortex-m3有关,这个芯片中有一个cortex-m3的事实与uart无关,uart要么被创建要么由Luminary Micro购买ip,然后被TI同化。 cortex-m3 只是处理器核心,大部分代码和文档等与 cortex-m3 无关。因为这个答案是用英文字母写的,但这个答案并没有详细说明这个事实。

这个答案可以很容易地用另一种语言写成,使用该语言的字母表。 cortex-m3 只是一种机制,您可以在其中戳控制寄存器并让外围设备执行操作。像这样的带有购买的 ip 内核的芯片从一个供应商那里获得内核,而芯片的其余部分要么是芯片供应商的 IP 要么是 collection 其他第三方 ip,或者两者的组合。

你的标题问题没有意义,因为 cortex-m3 没有 uart。您的实际问题与 LM3S811 芯片(不是电路板)及其 QEMU 实现有关,最好是使用 qemu 版本,但至少:“如何通过 LM3S811 QEMU 模拟回显数据”