当前位置: 首页 > article >正文

uboot中串口(控制台)初始化详解

1、串口初始化函数调用关系

start.S_startresetlowlevel_init uart_asm_init 	

1.1、uart_asm_init汇编函数

//根据配置文件中CONFIG_SERIALn[0:3]宏定义,决定初始化哪一个串口作为打印输出串口
#if defined(CONFIG_SERIAL1)
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART0_OFFSET)
#elif defined(CONFIG_SERIAL2)
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART1_OFFSET)
#elif defined(CONFIG_SERIAL3)
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART2_OFFSET) //X210开发板和S5PV210芯片都默认使用串口2
#elif defined(CONFIG_SERIAL4)
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART3_OFFSET)
#else
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART0_OFFSET)
#endifuart_asm_init:/* 设置GPIO模式成UART模式 */ldr	r0, =ELFIN_GPIO_BASEldr	r1, =0x22222222str   	r1, [r0, #GPA0CON_OFFSET]ldr     r1, =0x2222str     r1, [r0, #GPA1CON_OFFSET]//ELFIN_UART_CONSOLE_BASE = 要初始化的串口寄存器组的基地址ldr	r0, =ELFIN_UART_CONSOLE_BASE		mov	r1, #0x0str	r1, [r0, #UFCON_OFFSET]str	r1, [r0, #UMCON_OFFSET]/*接下来就是设置串口模式、波特率等,查看具体的寄存器说明*/mov	r1, #0x3str	r1, [r0, #ULCON_OFFSET]ldr	r1, =0x3c5str	r1, [r0, #UCON_OFFSET]ldr	r1, =UART_UBRDIV_VALstr	r1, [r0, #UBRDIV_OFFSET]ldr	r1, =UART_UDIVSLOT_VALstr	r1, [r0, #UDIVSLOT_OFFSET]ldr	r1, =0x4f4f4f4fstr	r1, [r0, #UTXH_OFFSET]		@'O'mov	pc, lr //函数返回

2、将串口设备注册到设备链表

2.1、函数调用关系

start.Sstart_armboot()devices_init ()drv_system_init ()device_register(&dev)

2.2、全局变量devlist

devlist是一个链表节点,将来uboot中新增的设备都注册该链表;devlist是在devices_init()函数里初始化的。

2.3、设备结构体

/* Device information */
typedef struct {int	flags;			/* Device flags: input/output/system	*/int	ext;			/* Supported extensions			*/char	name[16];		/* Device name				*//* GENERAL functions */int (*start) (void);		/* To start the device			*/int (*stop) (void);		/* To stop the device			*//* OUTPUT functions */void (*putc) (const char c);	/* To put a char			*/void (*puts) (const char *s);	/* To put a string (accelerator)	*//* INPUT functions */int (*tstc) (void);		/* To test if a char is ready...	*/int (*getc) (void);		/* To get that char			*//* Other functions */void *priv;			/* Private extensions			*/
} device_t;

这个结构体是用来描述一个输入输出设备的,putc、getc······指针将来要指向实际完成输入输出功能的函数,在构建设备结构体时会赋值。

2.4、drv_system_init函数

static void drv_system_init (void)
{device_t dev;memset (&dev, 0, sizeof (dev));strcpy (dev.name, "serial");//标志位标明该设备的用途,在初始化stdio_devices[]时会用到dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;//构建设备结构体dev.putc = serial_putc;dev.puts = serial_puts;dev.getc = serial_getc;dev.tstc = serial_tstc;//注册串口设备到设备链表device_register (&dev);	
}

2.5、device_register()函数

int device_register (device_t * dev)
{ListInsertItem (devlist, dev, LIST_END);return 0;
}

将新的设备结构体注册到devlist链表中。

3、全局变量stdio_devices[]

3.1、函数调用关系

start.Sstart_armboot()console_init_f()	//控制台第一阶段初始化console_init_r()	//控制台第二阶段初始化ListGetPtrToItem (devlist, i) //遍历已经注册的设备结构体console_setfile()	//将设备注册到stdio_devices[ ]

3.2、全局变量stdio_devices[]介绍

device_t *stdio_devices[] = { NULL, NULL, NULL };

是一个结构体数组,三个成员变量都是device_t结构体,对应stdin、stdout、stderr。

3.3、console_init_r()函数

int console_init_r (void) //实际使用
{device_t *inputdev = NULL, *outputdev = NULL;int i, items = ListNumItems (devlist);/* 在设备链表中根据标志位查找标准输入、标准输出设备 */for (i = 1;(i <= items) && ((inputdev == NULL) || (outputdev == NULL));i++) {device_t *dev = ListGetPtrToItem (devlist, i);if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {inputdev = dev;}if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {outputdev = dev;}}/* 将找到的标准输出设备结构体注册到stdio_devices[]全局变量中,其中标准输出和标准出错是同一个设备 */if (outputdev != NULL) {console_setfile (stdout, outputdev);console_setfile (stderr, outputdev);}/* 将找到的标准输入设备结构体注册到stdio_devices[]全局变量中 */if (inputdev != NULL) {console_setfile (stdin, inputdev);}/*修改gd全局变量的标准,表示设备初始化完成*/gd->flags |= GD_FLG_DEVINIT;	/* device initialization completed *//* 打印输入、输出、出错都是什么类型的设备 */puts ("In:      ");if (stdio_devices[stdin] == NULL) {puts ("No input devices available!\n");} else {printf ("%s\n", stdio_devices[stdin]->name);}puts ("Out:     ");if (stdio_devices[stdout] == NULL) {puts ("No output devices available!\n");} else {printf ("%s\n", stdio_devices[stdout]->name);}puts ("Err:     ");if (stdio_devices[stderr] == NULL) {puts ("No error devices available!\n");} else {printf ("%s\n", stdio_devices[stderr]->name);}return (0);
}

3.4、console_setfile()函数

static int console_setfile (int file, device_t * dev)
{int error = 0;if (dev == NULL)return -1;switch (file) {case stdin:case stdout:case stderr:/* Start new device */if (dev->start) {error = dev->start ();/* If it's not started dont use it */if (error < 0)break;}/* 将设备结构体注册到stdio_devices[] */stdio_devices[file] = dev; /** Update monitor functions* (to use the console stuff by other applications)*/switch (file) {case stdin:gd->jt[XF_getc] = dev->getc;gd->jt[XF_tstc] = dev->tstc;break;case stdout:gd->jt[XF_putc] = dev->putc;gd->jt[XF_puts] = dev->puts;gd->jt[XF_printf] = printf;break;}break;default:		/* Invalid file ID */error = -1;}return error;
}

初始化全局变量stdio_devices,stdin、stdout、stderr都有对应的设备结构体(一般三者都是指向同一个串口),调用printf()函数时会用到。

4、printf()函数用串口输出打印信息

参考博客:《uboot中printf( )函数实现分析》;

5、修改打印输出串口

#if defined(CONFIG_SERIAL1)
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART0_OFFSET)
#elif defined(CONFIG_SERIAL2)
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART1_OFFSET)
#elif defined(CONFIG_SERIAL3)//X210开发板和S5PV210芯片都默认使用串口2
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART2_OFFSET) 
#elif defined(CONFIG_SERIAL4)
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART3_OFFSET)
#else
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART0_OFFSET)
#endif#define CONFIG_SERIAL3          1	/* we use UART2 on SMDKC110 */

修改配置文件中的CONFIG_SERIALn[0:3]宏,比如定义CONFIG_SERIAL3就是代表使用串口2作输出。思路就是通过宏定义控制作为打印信息输出串口的寄存器组基地址。

http://www.lryc.cn/news/2413404.html

相关文章:

  • ORACLE 10G patch下载地址大全
  • HTML滚动条样式
  • 英语基本语法
  • PostScript基本语法
  • Handler机制(java层)
  • VirtualBox虚拟机网络怎么设置 VirtualBox虚拟机网络设置详细教程
  • 欧氏空间。
  • 文字竖着写怎么设置_微信置顶文字怎么设置 微信置顶文字的方法介绍|微信|置顶软硬件资讯川北在线...
  • 菜单栏的设计
  • 【博弈论】混合策略纳什均衡
  • PKI/CA基础知识整理
  • DSP芯片有什么特点?如何对DSP芯片进行分类?
  • SmartUpload
  • Union ADX 广告联盟系统介绍
  • 77. Combinations
  • Apache中VirtualHost配置说明
  • 编程软件索引2024
  • PHP基础详解(全)
  • PreferenceActivity简单用法
  • 天龙八部科举答题器
  • ModifyStyle函数的用法
  • ARM系列的命名含义及哪种ARM Cortex内核更适合我的应用
  • ic 查询网址
  • Linux服务器配置
  • windows10自动设置时间灰色怎么办
  • JQuery控制radio选中和不选中方法总结
  • 期货绝对稳赚的技巧
  • 计算机网络基础之以太网
  • kramer MTX3-34-M 34x34 8K 灵活模块化矩阵
  • 介绍一个新鲜玩意 开源的杀毒软件