我想为ARM编写一个裸机hello-world。消息应该在uart输出。设备树文件说明了uart:
uart@09000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x9000 0x1000>;
interrupts = <0x5>;
};
这是我的hello world program。
// vexpress.js:651
const int DR = 0x00;
const int FR = 0x18;
const int IBRD = 0x24;
const int FBRD = 0x28;
const int LCR_H = 0x2c;
const int CR = 0x30;
const int IFLS = 0x34;
const int IMSC = 0x38;
const int MIS = 0x40;
const int ICR = 0x44;
unsigned int *uart;
void
putc(char c)
{
// wait for UART to become ready to transmit
// vexpress.js:707
while ((uart[FR] & (1 << 7)));
uart[DR]= c;
while ((uart[FR] & (1 << 7)));
}
void
puts(char *s) {
while(*s)
putc(*(s++));
}
int
main()
{
char s[] = { 'H', 'a', 'l', 'l', 'o' , 0};
int i;
// vexpress.js:1455
uart = (unsigned int*)0x10009000;
// 1
putc('H');
putc('a');
putc('l');
putc('l');
putc('o');
putc(' ');
putc('W');
putc('e');
putc('l');
putc('t');
putc('\n');
putc('\r');
// 2
puts(s);
// 3
for(i=97;i<123;i++){
putc((char)i);
}
// 4
puts("Hello World\n\r");
while(1);
}
所以,这个程序使用几种输出方式给uart。第1部分(所有对putc的调用确实有效。但putc似乎不喜欢被循环调用。无论是2还是3还是4都没有用。第一个章程确实有效,奇怪的是'\ 0'之后被发送,而我不知道为什么。输出是
Hallo Welt
a\0\0\0\0.........
我使用arm-js,因为那是唯一一个足够完整的arm模拟器(mmu,可以运行linux),并且足够简单到单步(没有jit或类似)。
另外,有没有办法在构建时集成一个uart驱动程序来读取设备树文件的信息?是否有内核可以让我轻松使用该部分?
/编辑
cpu是ARMv5 cortex-a9 vexpress处理器。我不确定其他哪些信息是有意义的,所以
this is the device tree file和this is the assembler code
答案 0 :(得分:3)
uart = (unsigned int*)0x10009000;
while ((uart[FR] & (1 << 7)));
所以你要取0x10009000然后取一个变量FR,它被初始化为0x18并将其用作偏移量。 uart被定义为一个int,因此32位因此需要32位或4字节乘以0x18 = 0x60。所以你正在读取内存位置0x10009060,我怀疑你想要做什么。使用像这样的指针不是一个好的方法来做到这一点。 (您也未能将uart声明为volatile
)。 DR将是唯一一个工作为0 * 4 = 0的工具,你将得到地址0x10009000。
这些更新突出了一些问题,
const int FR = 6;
unsigned int volatile *uart;