am335x UART1输入u-boot 调试信息代码修改

Posted 陈富林

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了am335x UART1输入u-boot 调试信息代码修改相关的知识,希望对你有一定的参考价值。

 

AM335x 调试信息UART1输出代码修改
1. 关于pin_mux  的配置
代码修改位置:
/board/forlinx/ok335x/mux.c

1 void enable_uart0_pin_mux(void)                                                 
2 {                                                                               
3     configure_module_pin_mux(uart0_pin_mux_spl);                                
4     configure_module_pin_mux(uart1_pin_mux);                                    
5 }                                                                               
6                                                                                

将这行代码打开。

 

代码跟踪流程:
arch/arm/cpu/armv7/start.S :
开头的_start 函数:

1 .globl _start                                                                   
2 _start: b   reset   

 

从reset 函数跳入cpu_init_crit 函数,还是在本文件内:

 1 reset:                                                                          
 2     bl  save_boot_params                                                        
 3     /*                                                                          
 4      * set the cpu to SVC32 mode                                                
 5      */                                                                         
 6     mrs r0, cpsr                                                                
 7     bic r0, r0, #0x1f                                                           
 8     orr r0, r0, #0xd3                                                           
 9     msr cpsr,r0                
10     //......
11 #ifndef CONFIG_SKIP_LOWLEVEL_INIT                                               
12     bl  cpu_init_crit                                                           
13 #endif                                     
14     //......

 

从cpu_init_crit 函数进入lowlevel_init 函数。

这个函数在arch/arm/cpu/armv7/ti81xx/lowlevel_init.S 文件内。

 1 /*************************************************************************      
 2  *                                                                              
 3  * CPU_init_critical registers                                                  
 4  *                                                                              
 5  * setup important registers                                                    
 6  * setup memory timing                                                          
 7  *                                                                              
 8  *************************************************************************/     
 9 cpu_init_crit:                                                                  
10     /*                                                                          
11      * Invalidate L1 I/D                                                        
12      */                                                                         
13     mov r0, #0          @ set up for MCR                                        
14     mcr p15, 0, r0, c8, c7, 0   @ invalidate TLBs                               
15     mcr p15, 0, r0, c7, c5, 0   @ invalidate icache                             
16     mcr p15, 0, r0, c7, c5, 6   @ invalidate BP array                           
17     mcr     p15, 0, r0, c7, c10, 4  @ DSB                                       
18     mcr     p15, 0, r0, c7, c5, 4   @ ISB                                       
19     //......
20     bl  lowlevel_init       @ go setup pll,mux,memory  
21     //......

 

 

从lowlevel_init 函数进入s_init_start 函数。

 1 /*****************************************************************************  
 2  * lowlevel_init: - Platform low level init.                                    
 3  * Corrupted Register : r0, r1, r2, r3, r4, r5, r6                              
 4  ****************************************************************************/  
 5 .globl lowlevel_init                                                            
 6 lowlevel_init:                                                                  
 7                                                                                 
 8     /* The link register is saved in ip by start.S */                           
 9     mov r6, ip                                                                  
10     /* check if we are already running from RAM */                              
11     ldr r2, _lowlevel_init                                                      
12     ldr r3, _TEXT_BASE                                                          
13     sub r4, r2, r3                                                              
14     sub r0, pc, r4                                                             
15     //......
16     ands r0, r0, #0xC0000000 /* MSB 2 bits <> 0 then we are in ocmc or DDR */   
17     cmp r0, #0x80000000                                                         
18     bne s_init_start                                                            
19     mov r10, #0x01                                                              
20     b s_init_start                                                             
21 
22     //......


从s_init_start 函数进入s_init 函数。

1 s_init_start:                                                                   
2     mov r0, r10 /* passing in_ddr in r0 */                                      
3     bl s_init                                                                   
4     /* back to arch calling code */                                             
5     mov pc, r6                                                                  
6     /* the literal pools origin */                                              
7     .ltorg                                                                      
8                                                                                 
 1 /*                                                                              
 2  * early system init of muxing and clocks.                                      
 3  */                                                                             
 4 void s_init(void)                                                               
 5 {                                                                               
 6     /* Can be removed as A8 comes up with L2 enabled */                         
 7     l2_cache_enable();                                                          
 8                                                                                 
 9     /* WDT1 is already running when the bootloader gets control                 
10      * Disable it to avoid "random" resets                                      
11      */                                                                         
12     __raw_writel(0xAAAA, WDT_WSPR);                                             
13     while(__raw_readl(WDT_WWPS) != 0x0);                                        
14     __raw_writel(0x5555, WDT_WSPR);                                             
15     while(__raw_readl(WDT_WWPS) != 0x0);          
16 
17     //......
18     pll_init();
19     //......
20     enable_uart0_pin_mux();    
21 
22     //......
23 

这个函数的实现在board/forlinx/ok335x/evm.c 文件内.

从这里进入enable_uart0_pin_mux() ;

1 void enable_uart0_pin_mux(void)                                                 
2 {                                                                               
3     configure_module_pin_mux(uart0_pin_mux_spl);                                
4     configure_module_pin_mux(uart1_pin_mux);                                    
5 }                                                                               

 

这函数的实现在board/forlinx/ok335x/mux.c 文件内。

把这个uart1_pin_mux 的功能打开。

 

 

2. 关于uart1 时钟的配置
代码添加位置:
board/forlinx/ok335x/pll.c
per_clocks_enable 函数内,添加对uart1 始终的配置。

change by chen 2016/9/30 的即是我修改的。

 1 static void per_clocks_enable(void)                                             
 2 {                                                                               
 3     /* Enable the module clock */                                               
 4     __raw_writel(PRCM_MOD_EN, CM_PER_TIMER2_CLKCTRL);                           
 5     while (__raw_readl(CM_PER_TIMER2_CLKCTRL) != PRCM_MOD_EN);                  
 6                                                                                 
 7     /* Select the Master osc 24 MHZ as Timer2 clock source */                   
 8     __raw_writel(0x1, CLKSEL_TIMER2_CLK);                                       
 9                                                                                 
10     /* UART0 */                                                                 
11     __raw_writel(PRCM_MOD_EN, CM_WKUP_UART0_CLKCTRL);                           
12     while (__raw_readl(CM_WKUP_UART0_CLKCTRL) != PRCM_MOD_EN);                  
13                                                                                 
14     /* change by chen 2016/9/30 */                                              
15     __raw_writel(PRCM_MOD_EN, CM_PER_UART1_CLKCTRL);                            
16     while (__raw_readl(CM_PER_UART1_CLKCTRL) != PRCM_MOD_EN);                   
17                                                                                 
18     /* UART3 */                                                                 
19     __raw_writel(PRCM_MOD_EN, CM_PER_UART3_CLKCTRL);                            
20     while (__raw_readl(CM_PER_UART3_CLKCTRL) != PRCM_MOD_EN);                   
21                                                                                 
22     /* GPMC */                                                                  
23     __raw_writel(PRCM_MOD_EN, CM_PER_GPMC_CLKCTRL);                             
24     while (__raw_readl(CM_PER_GPMC_CLKCTRL) != PRCM_MOD_EN);                    
25     //.....
26 }

 

CM_PER_UART1_CLKCTR的宏定义设置在arch/arm/include/asm/arch-ti81xx/cpu.h文件内。

添加这一条宏定义。

1 #define CM_PER_UART1_CLKCTRL        (CM_PER + 0x6C) /* UART1 */                 
2 #define CM_PER_UART3_CLKCTRL        (CM_PER + 0x74) /* UART3 */                 

 

 

代码修改跟踪流程:

在上面已经跟踪的s_init 函数里面。

再进入pll_init () 函数。

 1 /*                                                                              
 2  * Configure the PLL/PRCM for necessary peripherals                             
 3  */                                                                             
 4 void pll_init()                                                                 
 5 {                                                                               //  mpu_pll_config(MPUPLL_M_500);                                               
 6     mpu_pll_config(MPUPLL_M_720);                                               
 7     core_pll_config();                                                          
 8     per_pll_config();                                                           
 9     ddr_pll_config();                                                           
10     /* Enable the required interconnect clocks */                               
11     interface_clocks_enable();                                                  
12     /* Enable power domain transition */                                        
13     power_domain_transition_enable();                                           
14     /* Enable the required peripherals */                                       
15     per_clocks_enable();                                                        
16 }                                                                              

这个函数的实现在:board/forlinx/ok335x/pll.c

再进入per_clocks_enable()函数内,这个函数在本文件内实现。

 1 /*                                                                              
 2  * Enable the module clock and the power domain for required peripherals        
 3  */                                                                             
 4 static void per_clocks_enable(void)                                             
 5 {                                                                               
 6     /* Enable the module clock */                                               
 7     __raw_writel(PRCM_MOD_EN, CM_PER_TIMER2_CLKCTRL);                           
 8     while (__raw_readl(CM_PER_TIMER2_CLKCTRL) != PRCM_MOD_EN);                  
 9                                                                                 
10     /* Select the Master osc 24 MHZ as Timer2 clock source */                   
11     __raw_writel(0x1, CLKSEL_TIMER2_CLK);                                       
12                                                                                 
13     /* UART0 */                                                                 
14     __raw_writel(PRCM_MOD_EN, CM_WKUP_UART0_CLKCTRL);                           
15     while (__raw_readl(CM_WKUP_UART0_CLKCTRL) != PRCM_MOD_EN);                  
16                                                                                 
17     /* change by chen 2016/9/30 */                                              
18     __raw_writel(PRCM_MOD_EN, CM_PER_UART1_CLKCTRL);                            
19     while (__raw_readl(CM_PER_UART1_CLKCTRL) != PRCM_MOD_EN);     
20     // ..................................
21 }

 

 



3. 关于include/configs/ok335x.h配置
代码修改位置:

1 #define CONFIG_SYS_NS16550_COM2     0x48022000   /* UART1 sbc-7109 */
2 
3 #define CONFIG_SERIAL2          1                                               
4 #define CONFIG_CONS_INDEX       2   

如上所示,添加这三个宏定义。
CONFIG_CONS_INDEX 这个为修改,原来uart0 输出调试信息的时候是为1。

 

代码跟踪流程:
arch/arm/cpu/armv7/start.S :从_start 进入reset 函数。

1 /* Set stackpointer in internal RAM to call board_init_f */                     
2 call_board_init_f:                                                              
3     ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)                                          
4     bic sp, sp, #7 /* 8-byte alignment for ABI compliance */                    
5     ldr r0,=0x00000000                                                          
6     bl  board_init_f                                                            

再进入board_init_f 函数。

 

 

这个函数的实现在:
arch/arm/lib/board.c 文件内。

 1 void board_init_f(ulong bootflag)                                               
 2 {                                                                               
 3     bd_t *bd;                                                                   
 4     init_fnc_t **init_fnc_ptr;                                                  
 5     gd_t *id;                                                                   
 6     ulong addr, addr_sp;                                                        
 7                                                                                 
 8                                                                                 
 9     /* Pointer is writable since we allocated a register for it */              
10     gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);                          
11     /* compiler optimization barrier needed for GCC >= 3.4 */                   
12     __asm__ __volatile__("": : :"memory");                                      
13                                                                                 
14     memset((void *)gd, 0, sizeof(gd_t));                                        
15                                                                                 
16     gd->mon_len = _bss_end_ofs;                                                 
17                                                                                 
18     for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {         
19         if ((*init_fnc_ptr)() != 0) {                                           
20             hang ();                                                            
21         }                                                                       
22     }                                                                           
23     //......
24 }

在这个函数内有for循环运行一系列的初始化。

这个数组有如下定义:

 1 init_fnc_t *init_sequence[] = {                                                 
 2 #if defined(CONFIG_ARCH_CPU_INIT)                                               
 3     arch_cpu_init,      /* basic arch cpu dependent setup */                    
 4 #endif                                                                          
 5 #if defined(CONFIG_BOARD_EARLY_INIT_F)                                          
 6     board_early_init_f,                                                         
 7 #endif                                                                          
 8     timer_init,     /* initialize timer */                                      
 9 #ifdef CONFIG_FSL_ESDHC                                                         
10     get_clocks,                                                                 
11 #endif                                                                          
12     env_init,       /* initialize environment */                                
13     init_baudrate,      /* initialze baudrate settings */                       
14     serial_init,        /* serial communications setup */                       
15     console_init_f,     /* stage 1 init of console */                           
16     display_banner,     /* say that we are here */                              
17 #if defined(CONFIG_DISPLAY_CPUINFO)                                             
18     print_cpuinfo,      /* display cpu info (and speed) */                      
19 #endif                                                                          
20 #if defined(CONFIG_DISPLAY_BOARDINFO)                                           
21     checkboard,     /* display board info */                                    
22     //.......
23 }

 


再进入serial_init 串行通信初始化。

这个函数的实现在:drivers/serial/serial.c 文件后内。

 1 #if !defined(CONFIG_SERIAL_MULTI)                                               
 2 int serial_init (void)                                                          
 3 {                                                                               
 4                                                                                 
 5     int clock_divisor;                                                          
 6                                                                                 
 7 #ifdef CONFIG_NS87308                                                           
 8     initialise_ns87308();                                                       
 9 #endif                                                                          
10                                                                                 
11 #ifdef CONFIG_SYS_NS16550_COM1                                                  
12     clock_divisor = calc_divisor(serial_ports[0]);                              
13     NS16550_init(serial_ports[0], clock_divisor);                               
14 #endif                                                                          
15 #ifdef CONFIG_SYS_NS16550_COM2                                                  
16     clock_divisor = calc_divisor(serial_ports[1]);                              
17     NS16550_init(serial_ports[1], clock_divisor);                               
18 #endif                                                                          
19 #ifdef CONFIG_SYS_NS16550_COM3                                                  
20     clock_divisor = calc_divisor(serial_ports[2]);                              
21     NS16550_init(serial_ports[2], clock_divisor);                               
22 #endif                                        
23 //......
24 }                                  

 


第一个CONFIG_SYS_NS16550_COM1为UART0的串口初始化。

第二个CONFIG_SYS_NS16550_COM2要自己定义,在include/configs/ok335x.h 内添加。

 

1 #define CONFIG_SYS_NS16550_COM2     0x48022000   /* UART1 sbc-7109 */           

这里的话只是完成了初始化,但是还要指定调试信息输出的端口。

 


回到arch/arm/lib/board.c
进入display_banner 函数,这个函数的实现在本文件内实现。

 1 static int display_banner(void)                                                 
 2 {                                                                               
 3     printf("\n\n%s\n\n", version_string);                                       
 4     printf("chen goto it ....\n") ;                                             
 5     debug("U-Boot code: %08lX -> %08lX  BSS: -> %08lX\n",                       
 6            _TEXT_BASE,                                                          
 7            _bss_start_ofs + _TEXT_BASE, _bss_end_ofs + _TEXT_BASE);             
 8 #ifdef CONFIG_MODEM_SUPPORT                                                     
 9     debug("Modem Support enabled\n");                                           
10 #endif                                                                          
11 #ifdef CONFIG_USE_IRQ                                                           
12     debug("IRQ Stack: %08lx\n", IRQ_STACK_START);                               
13     debug("FIQ Stack: %08lx\n", FIQ_STACK_START);                               
14 #endif                                                                          
15                                                                                 
16     return (0);                                                                 
17 }                                                                               


进入printf 函数,这个函数在/common/console.c 文件内实现。

 1 int printf(const char *fmt, ...)                                                
 2 {                                                                               
 3     va_list args;                                                               
 4     uint i;                                                                     
 5     char printbuffer[CONFIG_SYS_PBSIZE];                                        
 6                                                                                 
 7     va_start(args, fmt);                                                        
 8                                                                                 
 9     /* For this to work, printbuffer must be larger than                        
10      * anything we ever want to print.                                          
11      */                                                                         
12     i = vsprintf(printbuffer, fmt, args);                                       
13     va_end(args);                                                               
14                                                                                 
15     /* Print the string */                                                      
16     puts(printbuffer);                                                          
17     return i;                                                                   
18 }                                                                             

 

还是在本文件内,进入puts 函数:

 1 void puts(const char *s)                                                        
 2 {                                                                               
 3 #ifdef CONFIG_SILENT_CONSOLE                                                    
 4     if (gd->flags & GD_FLG_SILENT)                                              
 5         return;                                                                 
 6 #endif                                                                          
 7                                                                                 
 8 #ifdef CONFIG_DISABLE_CONSOLE                                                   
 9     if (gd->flags & GD_FLG_DISABLE_CONSOLE)                                     
10         return;                                                                 
11 #endif                                                                          
12                                                                                 
13     if (gd->flags & GD_FLG_DEVINIT) {                                           
14         /* Send to the standard output */                                       
15         fputs(stdout, s);                                                       
16     } else {                                                                    
17         /* Send directly to the handler */                                      
18         serial_puts(s);                                                         
19     }                                                                           
20 }                                                                              

 


再进入serial_puts 函数,这个函数的实现在drivers/serial/serial.c文件内实现。

1 void                                                                            
2 serial_puts(const char *s)                                                      
3 {                                                                               
4     _serial_puts(s,CONFIG_CONS_INDEX);                                          
5 }                                                                              


这里指定了输出的端口,这个宏定义也是在include/configs/ok335x.h 里面定义:

1 #define CONFIG_CONS_INDEX       2        

 

到此,在u-boot 阶段串口输出的调试信息即可以在UART1输出。

 

 

4. 关于kernel 调试信息的打印配置
在u-boot 文件夹内
include/configs/ok335x.h
将console=ttyO1 这样的话kernel 的调试信息也将在UART1输出。

 

 1 #ifdef CONFIG_android                                                           
 2 #define CON     \                                                               
 3     "console=ttyO0,115200n8 earlyprintk androidboot.console=ttyO0\0" \          
 4     "optargs=init=/init\0" \                                                    
 5     "mmcroot=/dev/mmcblk0p2 rw\0" \                                             
 6     "mmcrootfstype=ext4 rootwait\0" \                                           
 7     "nandroot=ubi0:rootfs rw ubi.mtd=7,2048\0" \                                
 8     "nandrootfstype=ubifs rootwait=1\0"                                         
 9 #else                                                                           
10 #define CON     \                                                               
11     "console=ttyO1,115200n8\0" \                                                
12     "optargs=\0" \                                                              
13     "mmcroot=/dev/mmcblk0p2 ro\0" \                                             
14     "mmcrootfstype=ext3 rootwait\0" \                                           
15     "nandroot=ubi0:rootfs rw ubi.mtd=7,2048\0" \                                
16     "nandrootfstype=ubifs rootwait=1\0"                                         
17 #endif                                                                          

 


5. 关于文件系统调试信息的配置
在文件系统目录。
etc/inittab

46行位UART1 输出,45行为UART0输出。

 45 #0:2345:respawn:/sbin/getty 115200 ttyO0
 46 1:2345:respawn:/sbin/getty 115200 ttyO1

 

以上是关于am335x UART1输入u-boot 调试信息代码修改的主要内容,如果未能解决你的问题,请参考以下文章

u-boot下延时程序失效的bug调试

Am335x u-boot 启动过程中的系统频率配置

am335x u-boot2011.09 SPL 流程跟踪

am335x uboot2016.05 (MLO u-boot.img)执行流程(转)

am335x系统升级之kernel uart

AM335x(TQ335x)学习笔记——挂载Ramdisk