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

 void enable_uart0_pin_mux(void)
{
configure_module_pin_mux(uart0_pin_mux_spl);
configure_module_pin_mux(uart1_pin_mux);
}

将这行代码打开。

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

 .globl _start
_start: b reset

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

 reset:
bl save_boot_params
/*
* set the cpu to SVC32 mode
*/
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr,r0
//......
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
//......

从cpu_init_crit 函数进入lowlevel_init 函数。

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

 /*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************/
cpu_init_crit:
/*
* Invalidate L1 I/D
*/
mov r0, # @ set up for MCR
mcr p15, , r0, c8, c7, @ invalidate TLBs
mcr p15, , r0, c7, c5, @ invalidate icache
mcr p15, , r0, c7, c5, @ invalidate BP array
mcr p15, , r0, c7, c10, @ DSB
mcr p15, , r0, c7, c5, @ ISB
//......
bl lowlevel_init @ go setup pll,mux,memory
//......

从lowlevel_init 函数进入s_init_start 函数。

 /*****************************************************************************
* lowlevel_init: - Platform low level init.
* Corrupted Register : r0, r1, r2, r3, r4, r5, r6
****************************************************************************/
.globl lowlevel_init
lowlevel_init: /* The link register is saved in ip by start.S */
mov r6, ip
/* check if we are already running from RAM */
ldr r2, _lowlevel_init
ldr r3, _TEXT_BASE
sub r4, r2, r3
sub r0, pc, r4
//......
ands r0, r0, #0xC0000000 /* MSB 2 bits <> 0 then we are in ocmc or DDR */
cmp r0, #0x80000000
bne s_init_start
mov r10, #0x01
b s_init_start //......

从s_init_start 函数进入s_init 函数。

 s_init_start:
mov r0, r10 /* passing in_ddr in r0 */
bl s_init
/* back to arch calling code */
mov pc, r6
/* the literal pools origin */
.ltorg
 /*
* early system init of muxing and clocks.
*/
void s_init(void)
{
/* Can be removed as A8 comes up with L2 enabled */
l2_cache_enable(); /* WDT1 is already running when the bootloader gets control
* Disable it to avoid "random" resets
*/
__raw_writel(0xAAAA, WDT_WSPR);
while(__raw_readl(WDT_WWPS) != 0x0);
__raw_writel(0x5555, WDT_WSPR);
while(__raw_readl(WDT_WWPS) != 0x0); //......
pll_init();
//......
enable_uart0_pin_mux(); //......

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

从这里进入enable_uart0_pin_mux() ;

 void enable_uart0_pin_mux(void)
{
configure_module_pin_mux(uart0_pin_mux_spl);
configure_module_pin_mux(uart1_pin_mux);
}

这函数的实现在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 的即是我修改的。

 static void per_clocks_enable(void)
{
/* Enable the module clock */
__raw_writel(PRCM_MOD_EN, CM_PER_TIMER2_CLKCTRL);
while (__raw_readl(CM_PER_TIMER2_CLKCTRL) != PRCM_MOD_EN); /* Select the Master osc 24 MHZ as Timer2 clock source */
__raw_writel(0x1, CLKSEL_TIMER2_CLK); /* UART0 */
__raw_writel(PRCM_MOD_EN, CM_WKUP_UART0_CLKCTRL);
while (__raw_readl(CM_WKUP_UART0_CLKCTRL) != PRCM_MOD_EN); /* change by chen 2016/9/30 */
__raw_writel(PRCM_MOD_EN, CM_PER_UART1_CLKCTRL);
while (__raw_readl(CM_PER_UART1_CLKCTRL) != PRCM_MOD_EN); /* UART3 */
__raw_writel(PRCM_MOD_EN, CM_PER_UART3_CLKCTRL);
while (__raw_readl(CM_PER_UART3_CLKCTRL) != PRCM_MOD_EN); /* GPMC */
__raw_writel(PRCM_MOD_EN, CM_PER_GPMC_CLKCTRL);
while (__raw_readl(CM_PER_GPMC_CLKCTRL) != PRCM_MOD_EN);
//.....
}

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

添加这一条宏定义。

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

代码修改跟踪流程:

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

再进入pll_init () 函数。

 /*
* Configure the PLL/PRCM for necessary peripherals
*/
void pll_init()
{ // mpu_pll_config(MPUPLL_M_500);
mpu_pll_config(MPUPLL_M_720);
core_pll_config();
per_pll_config();
ddr_pll_config();
/* Enable the required interconnect clocks */
interface_clocks_enable();
/* Enable power domain transition */
power_domain_transition_enable();
/* Enable the required peripherals */
per_clocks_enable();
}

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

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

 /*
* Enable the module clock and the power domain for required peripherals
*/
static void per_clocks_enable(void)
{
/* Enable the module clock */
__raw_writel(PRCM_MOD_EN, CM_PER_TIMER2_CLKCTRL);
while (__raw_readl(CM_PER_TIMER2_CLKCTRL) != PRCM_MOD_EN); /* Select the Master osc 24 MHZ as Timer2 clock source */
__raw_writel(0x1, CLKSEL_TIMER2_CLK); /* UART0 */
__raw_writel(PRCM_MOD_EN, CM_WKUP_UART0_CLKCTRL);
while (__raw_readl(CM_WKUP_UART0_CLKCTRL) != PRCM_MOD_EN); /* change by chen 2016/9/30 */
__raw_writel(PRCM_MOD_EN, CM_PER_UART1_CLKCTRL);
while (__raw_readl(CM_PER_UART1_CLKCTRL) != PRCM_MOD_EN);
// ..................................
}

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

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

 #define CONFIG_SERIAL2          1
#define CONFIG_CONS_INDEX 2

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

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

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

再进入board_init_f 函数。

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

 void board_init_f(ulong bootflag)
{
bd_t *bd;
init_fnc_t **init_fnc_ptr;
gd_t *id;
ulong addr, addr_sp; /* Pointer is writable since we allocated a register for it */
gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);
/* compiler optimization barrier needed for GCC >= 3.4 */
__asm__ __volatile__("": : :"memory"); memset((void *)gd, , sizeof(gd_t)); gd->mon_len = _bss_end_ofs; for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != ) {
hang ();
}
}
//......
}

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

这个数组有如下定义:

 init_fnc_t *init_sequence[] = {
#if defined(CONFIG_ARCH_CPU_INIT)
arch_cpu_init, /* basic arch cpu dependent setup */
#endif
#if defined(CONFIG_BOARD_EARLY_INIT_F)
board_early_init_f,
#endif
timer_init, /* initialize timer */
#ifdef CONFIG_FSL_ESDHC
get_clocks,
#endif
env_init, /* initialize environment */
init_baudrate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
display_banner, /* say that we are here */
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo, /* display cpu info (and speed) */
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard, /* display board info */
//.......
}

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

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

 #if !defined(CONFIG_SERIAL_MULTI)
int serial_init (void)
{ int clock_divisor; #ifdef CONFIG_NS87308
initialise_ns87308();
#endif #ifdef CONFIG_SYS_NS16550_COM1
clock_divisor = calc_divisor(serial_ports[]);
NS16550_init(serial_ports[], clock_divisor);
#endif
#ifdef CONFIG_SYS_NS16550_COM2
clock_divisor = calc_divisor(serial_ports[]);
NS16550_init(serial_ports[], clock_divisor);
#endif
#ifdef CONFIG_SYS_NS16550_COM3
clock_divisor = calc_divisor(serial_ports[]);
NS16550_init(serial_ports[], clock_divisor);
#endif
//......
}

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

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

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

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

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

 static int display_banner(void)
{
printf("\n\n%s\n\n", version_string);
printf("chen goto it ....\n") ;
debug("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
_TEXT_BASE,
_bss_start_ofs + _TEXT_BASE, _bss_end_ofs + _TEXT_BASE);
#ifdef CONFIG_MODEM_SUPPORT
debug("Modem Support enabled\n");
#endif
#ifdef CONFIG_USE_IRQ
debug("IRQ Stack: %08lx\n", IRQ_STACK_START);
debug("FIQ Stack: %08lx\n", FIQ_STACK_START);
#endif return ();
}

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

 int printf(const char *fmt, ...)
{
va_list args;
uint i;
char printbuffer[CONFIG_SYS_PBSIZE]; va_start(args, fmt); /* For this to work, printbuffer must be larger than
* anything we ever want to print.
*/
i = vsprintf(printbuffer, fmt, args);
va_end(args); /* Print the string */
puts(printbuffer);
return i;
}

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

 void puts(const char *s)
{
#ifdef CONFIG_SILENT_CONSOLE
if (gd->flags & GD_FLG_SILENT)
return;
#endif #ifdef CONFIG_DISABLE_CONSOLE
if (gd->flags & GD_FLG_DISABLE_CONSOLE)
return;
#endif if (gd->flags & GD_FLG_DEVINIT) {
/* Send to the standard output */
fputs(stdout, s);
} else {
/* Send directly to the handler */
serial_puts(s);
}
}


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

 void
serial_puts(const char *s)
{
_serial_puts(s,CONFIG_CONS_INDEX);
}


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

 #define CONFIG_CONS_INDEX       2        

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

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

 #ifdef CONFIG_ANDROID
#define CON \
"console=ttyO0,115200n8 earlyprintk androidboot.console=ttyO0\0" \
"optargs=init=/init\0" \
"mmcroot=/dev/mmcblk0p2 rw\0" \
"mmcrootfstype=ext4 rootwait\0" \
"nandroot=ubi0:rootfs rw ubi.mtd=7,2048\0" \
"nandrootfstype=ubifs rootwait=1\0"
#else
#define CON \
"console=ttyO1,115200n8\0" \
"optargs=\0" \
"mmcroot=/dev/mmcblk0p2 ro\0" \
"mmcrootfstype=ext3 rootwait\0" \
"nandroot=ubi0:rootfs rw ubi.mtd=7,2048\0" \
"nandrootfstype=ubifs rootwait=1\0"
#endif

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

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

  #::respawn:/sbin/getty  ttyO0
::respawn:/sbin/getty ttyO1

am335x UART1输入u-boot 调试信息代码修改的更多相关文章

  1. 在vscode中进行nodejs服务端代码调试(代码修改自动重启服务端)

    使用到的是nodemon,具体在package.json文件中配置如下: "scripts": { "start": "node ./bin/www& ...

  2. 利用 Serial Over Lan(SOL)搭建 XEN 的调试信息输出环境

    如有转载,请注明出处与本文连接,谢谢! 修改XEN的源码实现额外的功能,需要有一个调试环境来得到XEN的调试信息(有关源码编译并安装 XEN 请阅读我以前的博文:在CentOS下源码安装 Xen并搭建 ...

  3. 利用chrome调试JavaScript代码

    看见网上很多人问怎么用chrome调试JavaScript代码,我也对这个问题抱着疑问,但是没有找到一篇能用的中文文章(可能我的google有问题),也不知道怎么点出一篇E文的,感觉作者写得不错,所以 ...

  4. lr 增强窗格中,如何生成调试信息?

    我是根据电子书来操作的, 如何生成调试信息?在测试运行的某些时候,经常需要向输出设备发送消息,指出当前位置和其他信息.这些输出消息会出现在回放日志和 Controller 的输出窗口中.可以发送标准输 ...

  5. Android调试系列—使用android studio调试smali代码

    1.工具介绍 使用工具 android killer:用于反编译apk包,得到smali代码 android studio:调试smali代码工具,或者使用idea,android studio就是在 ...

  6. OpenGL笔记<5> shader 调试信息获取 Debug

    我们今天来讲调试信息,这个东西讲起来会比较无聊,因为都是一些函数调用,没啥可讲的,函数就是那样用的,不过其效果挺好玩的,同时在程序设计中也是很必要的,所以还是来写一下,不过,就是因为知识比较固定且简单 ...

  7. 【转】VC调试的时候 “没有调试信息,未加载符号”

    概述调试是一个程序员最基本的技能,其重要性甚至超过学习一门语言.不会调试的程序员就意味着他即使会一门语言,却不能编制出任何好的软件.这里我简要的根据自己的经验列出调试中比较常用的技巧,希望对大家有用. ...

  8. 利用pycharm远程调试openstack代码

    1.安装pycharm专业版 本文安装pycharm 2016.2.3专业版.网上教程较多,这里不做详细介绍,只要到pycharm官网上下载应用程序进行安装即可. 2.pycharm配置 (1)首先按 ...

  9. 如何调试Javascript代码

    转自原文如何调试Javascript代码 目前,常用的浏览器IE.Chrome.Firefox都有相应的脚本调试功能.作为我们.NET 阵营,学会如何在IE中调试JS就足够了,在掌握了IE中的调试方法 ...

随机推荐

  1. join和setdaemon()初探

    join()方法:主线程A中,创建了子线程B,并且在主线程A中调用了B.join(),那么主线程A会在调用的地方等待,直到子线程B完成操作后,才可以接着往下执行,那么在调用这个线程时可以使用被调用线程 ...

  2. 微信H5手指滑动屏蔽微信的默认效果

    我们的H5页面放在微信上时,如果你向上滑动或者向下滑动屏幕时,会发现一些微信的特征,譬如:网页由www.baidu.com提供. 去掉这个微信的特征,代码如下: var f; n.addEventLi ...

  3. Red Black Tree in C

    http://web.mit.edu/~emin/www.old/source_code/red_black_tree/index.html

  4. 分享jquery实现百叶窗特效的图片轮播

    首先非常感谢网友嘉翼的无私分享,这是他刚在网站扣下来的特效,第一时间与大家分享,jquery实现百叶窗特效的图片轮播 使用方法: 1.引用css文件,css文件里面已经做了注释,基本只需要修改宽高就好 ...

  5. .net mvc web api 返回 json 内容,过滤值为null的属性

    原文:http://blog.csdn.net/xxj_jing/article/details/49508557 版权声明:本文为博主原创文章,未经博主允许不得转载. .net mvc web ap ...

  6. Yii2 advanced版API接口开发 基于RESTful架构的 配置、实现、测试

    参考地址: http://www.xiaoxiangzi.com/Programme/PHP/3348.html http://www.cnblogs.com/ganiks/p/yii2-restfu ...

  7. jsp系统时间和时间对比(活动结束不结束)

    jsp页面拿到系统时间 <jsp:useBean id="now" class="java.util.Date" /> <fmt:format ...

  8. 只有文本编辑器才是王道, 什么ide都是evil的浮云, 看看linus linux的内核开发工具vim emacs

    只有文本编辑器才是王道, 什么ide都是evil的浮云, 看看linus linux的内核开发工具vim emacs [ide is evil] (http://i.cnblogs.com/EditP ...

  9. 清空mysql表后,自增id复原

    alter table `ajy_servercategory` AUTO_INCREMENT=1; alter table `Table_Name` AUTO_INCREMENT=n; 一.清除my ...

  10. Linux服务器管理: RPM包

    服务安装类型主要分两种: RPM安装和源码包编译安装: 1.RPM包查看: rpm -qa | grep 包名 用chkconfig --list 查看服务自启动命令    只对RPM包安装的服务生效 ...