微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > GNU ARM汇编--(十五)linux下的printascii

GNU ARM汇编--(十五)linux下的printascii

时间:11-26 来源:互联网 点击:
在前面对很多s3c2440的功能模块进行学习后,已经具备了将这些模块综合起来的条件,基于此,将前面的代码综合成一个简单的bootloader.自己写的bootloader在引导kernel的时候,串口输出只有Uncompressing Linux...和done, booting the kernel。串口有这个输出,说明kernel被正确引导了,但是串口有问题。

这篇blog只是分析解决这个问题的第一步:

既然"Uncompressing Linux..."这句打印是kernel代码中的,那kernel的其他打印怎么没有?

在archarmootcompressed目录下的misc.c中,上面的打印是在decompress_kernel函数中,而该函数是在kernel的初始汇编中调用的,也就是说这个时候kernel的串口驱动肯定是没有工作的,那这里的串口输出只能是用bootloader初始化好的串口,

putstr("Uncompressing Linux...");

putstr(" done, booting the kernel.");

[html]view plaincopy

  1. staticvoidputstr(constchar*ptr)
  2. {
  3. charc;
  4. while((c=*ptr++)!=){
  5. if(c==)
  6. putc();
  7. putc(c);
  8. }
  9. flush();
  10. }


在includeasm-armplat-s3uncompress.h中,有putc函数的定义:

[html]view plaincopy

  1. staticvoidputc(intch)
  2. {
  3. if(uart_rd(S3C2410_UFCON)&S3C2410_UFCON_FIFOMODE){
  4. intlevel;
  5. while(1){
  6. level=uart_rd(S3C2410_UFSTAT);
  7. level&=fifo_mask;
  8. if(level
  9. break;
  10. }
  11. }else{
  12. /*notusingfifos*/
  13. while((uart_rd(S3C2410_UTRSTAT)&S3C2410_UTRSTAT_TXE)!=S3C2410_UTRSTAT_TXE)
  14. barrier();
  15. }
  16. /*writebytetotransmissionregister*/
  17. uart_wr(S3C2410_UTXH,ch);
  18. }

从这里可以看到,这里的输出的确是利用了bootloader中对串口的初始化,但是这部分代码还是通用的:不管在bootloader中将串口初始化为用fifo还是非fifo的,这一小块代码都是可以正常串口输出的。

既然明白了这两句打印为什么可以输出后,就要排查后续没有打印的原因了,这里我们就利用printascii函数来debug,我们知道kernel的printf函数是printk,在printk函数内部添加printascii函数,make menuconfig中选中:

Kernel hacking下的[*] Kernel low-level debugging functions下的[*] Kernel low-level debugging messages via S3C UART,并选择(0) S3C UART to use for low-level debug

Device Drivers -->Character devices-->Serial drivers--><*> Samsung S3C2410/S3C2440/S3C2442/S3C2412 Serial port support和[*] Support for console on S3C2410 serial port

printk函数修改如下:

[cpp]view plaincopy

  1. asmlinkageintprintk(constchar*fmt,...)
  2. {
  3. va_listargs;
  4. intr;
  5. #ifdefCONFIG_DEBUG_LL
  6. externvoidprintascii(constchar*);
  7. charbuff[256];
  8. #endif
  9. va_start(args,fmt);
  10. r=vprintk(fmt,args);
  11. #ifdefCONFIG_DEBUG_LL
  12. vsprintf(buff,fmt,args);
  13. #endif
  14. va_end(args);
  15. #ifdefCONFIG_DEBUG_LL
  16. printascii(buff);
  17. #endif
  18. returnr;
  19. }



重新编译内核烧写后,发现kernel的输出都有了,这说明kernel的串口驱动有问题,或者说要去研究要bootloader如何向kernel传递参数的。另外一个疑惑就是printk没有输出,为什么printascii有输出呢?

查看源码才知道,printascii是针对arm平台的debug函数:

在archarmkerneldebug.S中

[html]view plaincopy

  1. ENTRY(printascii)
  2. addruartr3
  3. b2f
  4. 1:waituartr2,r3
  5. senduartr1,r3
  6. busyuartr2,r3
  7. teqr1,#
  8. moveqr1,#
  9. beq1b
  10. 2:teqr0,#0
  11. ldrnebr1,[r0],#1
  12. teqner1,#0
  13. bne1b
  14. movpc,lr


在includeasm-armarch-s3c241debug-macro.S中,addruart宏定义如下:

[html]view plaincopy

  1. .macroaddruart,rx
  2. mrcp15,0,x,c1,c0
  3. tstx,#1
  4. ldreqx,=S3C24XX_PA_UART
  5. ldrnex,=S3C24XX_VA_UART
  6. #ifCONFIG_DEBUG_S3C_UART!=0
  7. addx,x,#(S3C2410_UART1_OFF*CONFIG_DEBUG_S3C_UART)
  8. #endif
  9. .endm

从p15协处理器来查看MMU是否打开了,从而用PA或者VA,这说明MMU打开前或者后都可以用printascii进行debug。

在includeasm-armplat-s3cdebug-macro.S中,有senduart、busyuart和waituart的定义,具体代码就不贴出来了,这三个代码实现了串口的输出,这三个宏定义针对fifo和非fifo的情况都做了处理,保证代码的健壮。

到这里,可以看出来printascii基于bootloader或者kernel对串口的初始化后才能起作用,但一般用printascii辅助debug主要用于kernel的最开始部分,这时候的串口初始化用的还是bootloader的。当然,在kernel的串口驱动正常工作后,printascii同样是起作用的。最后,printascii代码还是很健壮的,而且printascii的生命周期也是相当长的,从kernel启动开始到kernle关闭之时,printascii都是

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top