U-Boot串口初始化详解

U-Boot串口初始化详解

目录

零、概述
一、init_baudrate
二、serial_init
三、console_init_f
四、devices_init
五、console_init_r
六、打印信息
七、为什么要使用devlist,std_device[]?

零、概述


上面这张图是U-Boot中串口设备驱动的流程,从寄存器级别的设置到最后终端信息的输出。下面我们详细讲解每一个步骤。

一、init_baudrate

该函数设置了gd->bd->bi_baudrate。

[plain]  view plain copy
  1. static int init_baudrate (void)  
  2. {  
  3.     char tmp[64];   /* long enough for environment variables */  
  4.     int i = getenv_r ("baudrate", tmp, sizeof (tmp));  
  5.     gd->bd->bi_baudrate = gd->baudrate = (i > 0)  
  6.             ? (int) simple_strtoul (tmp, NULL, 10)  
  7.             : CONFIG_BAUDRATE;  
  8. //#define CONFIG_BAUDRATE   115200  定义在/include/configs/smdk2410.c中  
  9. //如果环境中没有保存,则使用宏定义的参数  
  10.     return (0);  
  11. }  

二、serial_init

UART控制器的初始化。

[plain]  view plain copy
  1. void serial_setbrg (void)  
  2. {  
  3.     S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);  
  4.     int i;  
  5.     unsigned int reg = 0;  
  6.   
  7.     /* value is calculated so : (int)(PCLK/16./baudrate) -1 */  
  8.     reg = get_PCLK() / (16 * gd->baudrate) - 1;  
  9.   
  10.     /* FIFO enable, Tx/Rx FIFO clear */  
  11.     uart->UFCON = 0x07;  
  12.     uart->UMCON = 0x0;  
  13.     /* Normal,No parity,1 stop,8 bit */  
  14.     uart->ULCON = 0x3;  
  15.     /*  
  16.      * tx=level,rx=edge,disable timeout int.,enable rx error int.,  
  17.      * normal,interrupt or polling  
  18.      */  
  19.     uart->UCON = 0x245;  
  20.     uart->UBRDIV = reg;  
  21.   
  22. #ifdef CONFIG_HWFLOW  
  23.     uart->UMCON = 0x1; /* RTS up */  
  24. #endif  
  25.     for (i = 0; i < 100; i++);  
  26. }  
  27.   
  28. /*  
  29.  * Initialise the serial port with the given baudrate. The settings  
  30.  * are always 8 data bits, no parity, 1 stop bit, no start bits.  
  31.  *  
  32.  */  
  33. int serial_init (void)  
  34. {  
  35.     serial_setbrg ();//UART寄存器设置  
  36.   
  37.     return (0);  
  38. }  

三、console_init_f

控制台的前期初始化。

[plain]  view plain copy
  1. int console_init_f (void)  
  2. {  
  3.     gd->have_console = 1;  
  4.   
  5. #ifdef CONFIG_SILENT_CONSOLE  
  6.     if (getenv("silent") != NULL)  
  7.         gd->flags |= GD_FLG_SILENT;  
  8. #endif  
  9.   
  10.     return (0);  
  11. }  

四、devices_init

这一部分在前面的文章已经分析过了,这里就不在叙述了。

五、console_init_r

控制台后期初始化。查看环境参数stdin,stdout,stderr中对标准IO的指定的设备名称,如果没有知道再按照环境指定的名称搜索devlist,将搜到的设备指针赋给标准IO数组stdio_devices[]。

[plain]  view plain copy
  1. int console_init_r (void)  
  2. {  
  3.     char *stdinname, *stdoutname, *stderrname;  
  4.     device_t *inputdev = NULL, *outputdev = NULL, *errdev = NULL;  
  5. #ifdef CFG_CONSOLE_ENV_OVERWRITE  
  6.     int i;  
  7. #endif /* CFG_CONSOLE_ENV_OVERWRITE */  
  8.   
  9.     /* set default handlers at first 设置跳转表*/  
  10.     gd->jt[XF_getc] = serial_getc;  
  11.     gd->jt[XF_tstc] = serial_tstc;  
  12.     gd->jt[XF_putc] = serial_putc;  
  13.     gd->jt[XF_puts] = serial_puts;  
  14.     gd->jt[XF_printf] = serial_printf;  
  15.   
  16.     /* stdin stdout and stderr are in environment 查看环境参数stdin,stdout,stderr中对标准IO的指定的设备名称*/  
  17.     /* scan for it */  
  18.     stdinname  = getenv ("stdin");  
  19.     stdoutname = getenv ("stdout");  
  20.     stderrname = getenv ("stderr");  
  21.   
  22.     if (OVERWRITE_CONSOLE == 0) {   /* if not overwritten by config switch */  
  23.         inputdev  = search_device (DEV_FLAGS_INPUT,  stdinname);  
  24.         outputdev = search_device (DEV_FLAGS_OUTPUT, stdoutname);  
  25.         errdev    = search_device (DEV_FLAGS_OUTPUT, stderrname);  
  26.     }  
  27.     /* if the devices are overwritten or not found, use default device 按指定的名称搜索设备*/  
  28.     if (inputdev == NULL) {  
  29.         inputdev  = search_device (DEV_FLAGS_INPUT,  "serial");  
  30.     }  
  31.     if (outputdev == NULL) {  
  32.         outputdev = search_device (DEV_FLAGS_OUTPUT, "serial");  
  33.     }  
  34.     if (errdev == NULL) {  
  35.         errdev    = search_device (DEV_FLAGS_OUTPUT, "serial");  
  36.     }  
  37.     /* Initializes output console first将搜到的设备指针赋给标准IO数组stdio_devices[],在下面会将为什么要这样做 */  
  38.     if (outputdev != NULL) {  
  39.         console_setfile (stdout, outputdev);  
  40.     }  
  41.     if (errdev != NULL) {  
  42.         console_setfile (stderr, errdev);  
  43.     }  
  44.     if (inputdev != NULL) {  
  45.         console_setfile (stdin, inputdev);  
  46.     }  
  47.   
  48.     gd->flags |= GD_FLG_DEVINIT; /* device initialization completed,到此串口设备才初始化完成,这个标志会影响getc等函数 */  
  49.   
  50. #ifndef CFG_CONSOLE_INFO_QUIET  
  51.     /* Print information 打印信息*/  
  52.     puts ("In:    ");  
  53.     if (stdio_devices[stdin] == NULL) {  
  54.         puts ("No input devices available!\n");  
  55.     } else {  
  56.         printf ("%s\n", stdio_devices[stdin]->name);  
  57.     }  
  58.   
  59.     puts ("Out:   ");  
  60.     if (stdio_devices[stdout] == NULL) {  
  61.         puts ("No output devices available!\n");  
  62.     } else {  
  63.         printf ("%s\n", stdio_devices[stdout]->name);  
  64.     }  
  65.   
  66.     puts ("Err:   ");  
  67.     if (stdio_devices[stderr] == NULL) {  
  68.         puts ("No error devices available!\n");  
  69.     } else {  
  70.         printf ("%s\n", stdio_devices[stderr]->name);  
  71.     }  
  72. #endif /* CFG_CONSOLE_INFO_QUIET */  
  73.   
  74. #ifdef CFG_CONSOLE_ENV_OVERWRITE  
  75.     /* set the environment variables (will overwrite previous env settings) */  
  76.     for (i = 0; i < 3; i++) {  
  77.         setenv (stdio_names[i], stdio_devices[i]->name);  
  78.     }  
  79. #endif /* CFG_CONSOLE_ENV_OVERWRITE */  
  80.   
  81. #if 0  
  82.     /* If nothing usable installed, use only the initial console */  
  83.     if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))  
  84.         return (0);  
  85. #endif  
  86.     return (0);  
  87. }  

六、打印信息

在最后会打印出如下信息:

In:    serial
Out:   serial
Err:   serial

这说明串口初始化完成。

七、为什么要使用devlist,std_device[]?

为了更灵活地实现标准IO重定向,任何可以作为标准IO的设备,如USB键盘,LCD屏,串口等都可以对应一个device_t的结构体变量,只需要实现getc和putc等函数,就能加入到devlist列表中去,也就可以被assign为标准IO设备stdo_device中去。如函数 int console_assign (int file, char *devname); /* Assign the console 重定向标准输入输出*/这个函数功能就是把名为devname的设备重定向为标准IO文件file(stdin,stdout,stderr)。其执行过程是在devlist中查找devname的设备,返回这个设备的device_t指针,并把指针值赋给stdo_device[file]。

[plain]  view plain copy
  1. int console_assign (int file, char *devname)  
  2. {  
  3.     int flag, i;  
  4.   
  5.     /* Check for valid file */  
  6.     switch (file) {  
  7.     case stdin:  
  8.         flag = DEV_FLAGS_INPUT;  
  9.         break;  
  10.     case stdout:  
  11.     case stderr:  
  12.         flag = DEV_FLAGS_OUTPUT;  
  13.         break;  
  14.     default:  
  15.         return -1;  
  16.     }  
  17.   
  18.     /* Check for valid device name */  
  19.   
  20.     for (i = 1; i <= ListNumItems (devlist); i++) {  
  21.         device_t *dev = ListGetPtrToItem (devlist, i);  
  22.   
  23.         if (strcmp (devname, dev->name) == 0) {  
  24.             if (dev->flags & flag)  
  25.                 return console_setfile (file, dev);  
  26.   
  27.             return -1;  
  28.         }  
  29.     }  
  30.   
  31.     return -1;  
  32. }  
该函数是调用console_setfile设置stdo_device[]完成重定向输入输出。

[plain]  view plain copy
  1. static int console_setfile (int file, device_t * dev)  
  2. {  
  3.     int error = 0;  
  4.   
  5.     if (dev == NULL)  
  6.         return -1;  
  7.   
  8.     switch (file) {  
  9.     case stdin:  
  10.     case stdout:  
  11.     case stderr:  
  12.         /* Start new device */  
  13.         if (dev->start) {  
  14.             error = dev->start ();  
  15.             /* If it's not started dont use it */  
  16.             if (error < 0)  
  17.                 break;  
  18.         }  
  19.   
  20.         /* Assign the new device (leaving the existing one started) */  
  21.         stdio_devices[file] = dev;//这里是关键  
  22.   
  23.         /*  
  24.          * Update monitor functions  
  25.          * (to use the console stuff by other applications)  
  26.          */  
  27.         switch (file) {  
  28.         case stdin:  
  29.             gd->jt[XF_getc] = dev->getc;  
  30.             gd->jt[XF_tstc] = dev->tstc;  
  31.             break;  
  32.         case stdout:  
  33.             gd->jt[XF_putc] = dev->putc;  
  34.             gd->jt[XF_puts] = dev->puts;  
  35.             gd->jt[XF_printf] = printf;  
  36.             break;  
  37.         }  
  38.         break;  
  39.   
  40.     default:        /* Invalid file ID */  
  41.         error = -1;  
  42.     }  
  43.     return error;  
  44. }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值