最近一个多月没有白忙乎,终于把LPC2294的Linux跑起来了.大概的问题和解决办法是这样的.
问题1:装载linux错误,在内存中看到的代码二进制形式和实际的不一样.
解决1:linux下载之前设置的BCFG不对,要注意两个问题:一个是SRAM的位数错误,一个是速度太快.
问题2:装载正确,但是运行时串口没有任何数据输出.
解决2:串口的使能问题,由于该实验板的外设全部用SPI控制使能,之前需要发送使能信号.所以这个工作需要在bootloader里完成.
问题3:串口使能,但是还是不能正常运行.
解决3:bootloader中有对PLL的初始化,如果和Linux中初始化的不一致,就会出现问题.Linux中PLL的初始化是在make menuconfig里面对时钟进行设置,包括内部的华外围的.设置了之后在head.s文件中体现出来.将head.s和bootloader和config里的统一即可.
问题4:可以看到Linux初始化信息,但是死在了calibrate loop里面.
解决4:这个函数是Linux自启动以来用到的第一个中断函数.死在这里,说明中断向量的设置有问题.
首先检查memmap是否设置正确,一般可以映射到外部flash空间,即0x03.然后检查flash里面是否有中断表,这个可以在BOOTLOADER里面设置完成,ADS用DCD,GCC用.long.中断表的跳转地址是0x81000000.为什么要从flash跳到SRAM中,是因为Linux在trap_init的的时候把中断表复制到81000000处,然后在该处还有一次跳转,目的地址是0x81000200,这个200处的复制工作也是由linux完成的.
经过读代码发现,Linux的中断函数的类型是interrupt_t,实际上就是个int,而且它的中断函数是具有参数的,很奇怪.这只有两种情况,一种是它不是在中断的时候执行的,另一种情况是它的参数并没有传递进去.通过研究81000200处的代码(arch/arm/kernel/entry-armv.s)发现它早已在执行中断函数之前恢复成为SVC态了.原来它就是个普通函数,只不过在中断表中被调用了而已.
问题5:启动过了calibrate loop之后,不断出现Unhandled alignment exception....但是在出错之后重新LOAD一次就好用.
解决5:由于出错后再装载可以正常使用,说明出错的时候将某个值设置正确了.bootloader被设置成了USR模式,应该在进入Linux之前设置成为SVC.这个和中断也有很大的关系.
问题6:在Freeing init memory之后,串口出现too much work for irqx.
解决6:通过跟踪代码,发现在drivers/serial/8250.c文件的serial8250_startup函数中,有这么几句话:
/*
* Finally, enable interrupts. Note: Modem status interrupts
* are set via set_termios(), which will be occurring imminently
* anyway, so we don't enable them here.
*/
up->ier = UART_IER_RLSI | UART_IER_RDI;
serial_outp(up, UART_IER, up->ier);
中断使能寄存器的再次设置导致了串口输出的错误.将最后一句注释掉,即可正常工作.