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

kb5ga3dv  于 2023-06-30  发布在  其他
关注(0)|答案(1)|浏览(107)

我试图等待来自UART的字符,然后传输回UART,我已经附加了.c文件,启动和链接器代码。我使用Qemu仿真LM 3S 811 ARM Cortex-M3板。但是我的qemu给出了以下错误。其实这是我对上一篇文章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;  
}

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

llmtgqce

llmtgqce1#

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

第0位被标记为保留,所以这段代码不会做任何有用的事情。
第4章说
RXFE
UART接收FIFO为空
此位的含义取决于UARTLCRH寄存器中FEN位的状态。
如果FIFO禁用,则当接收保持寄存器为空时,该位置1。
如果FIFO使能,则当接收FIFO为空时,该位置1。
因此独立于FEN控制位。位4在fifo为空时置位,这意味着当它从1变为0时,至少接收到一个字符。
所以呢

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

位5在tx缓冲器已满时置位,这意味着没有更多空间。所以呢

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;
}

使用0x 20或(1<<5)的利弊,显然两者是相同的。两者都提供了更好的可读性和验证,具体取决于个人以及他们如何使用/阅读手册等。
我发现的问题是,如果你按住键盘上的键,并重复到虚拟终端,它似乎溢出了模拟的rx缓冲区和字符的爆炸出来。在真实的的硬件上不会有这个问题。qemu是开源的,所以你可以很容易地去阅读代码,看看是怎么回事。可能它想要一个更准确/正确的uart init,因为真实的硬件上的uart将无法使用所编写的代码。需要UART初始化。
要知道,这一切都与cortex-m3无关,事实上,在这个芯片中有一个cortex-m3与uart无关,uart是由Luminary Micro创建或购买的ip,然后被TI吸收。Cortex-M3只是处理器核心,大部分代码和文档等与Cortex-M3无关。因为这个答案是用英语字母写的,但这个答案并没有详细说明这个事实。
这个答案可以很容易地用另一种语言用该语言的字母表写出来。cortex-m3只是一种机制,在这种机制中,你可以访问控制寄存器,让外围设备做一些事情。具有购买的IP核的这样的芯片从一个供应商获得核,并且芯片的其余部分是芯片供应商的IP或其他第三方IP的集合,或者是组合。
你的标题问题没有意义,因为cortex-m3没有uart。你的实际问题与LM 3S 811芯片(不是板)和QEMU实现有关,理想情况下是qemu版本,但至少:“如何通过LM 3S 811 QEMU仿真回显数据”

相关问题