您的位置:首页 > 运维架构 > 网站架构

ARM架构处理器MT6572的LK printf 与UART串口打印分析

2013-11-23 11:52 656 查看
相关源码文件:

bootable/bootloader/lk/include/printf.h

bootable/bootloader/lk/lib/libc/printf.c



其他参考文章:

MT6572的LK(可以理解为UBOOT)uart串口驱动分析【代码注释】 /article/1917761.html







关于printf的如果调到串口发送函数的,以及printf的实现和调用流程如下:



bootable/bootloader/lk/lib/libc/printf.c

int printf(const char *fmt, ...)

{

int err;

va_list ap;

va_start(ap, fmt);

err = _dvprintf(fmt, ap);

va_end(ap);

return err;

}

bootable/bootloader/lk/lib/debug/debug.c

int _dvprintf(const char *fmt, va_list ap)

{

char buf[256];

int err;

err = vsnprintf(buf, sizeof(buf), fmt, ap);

dputs(ALWAYS, buf);

return err;

}



bootable/bootloader/lk/include/debug.h:

#define dputs(level, str) do { if ((level) <= DEBUGLEVEL) { _dputs(str); } } while (0)

int _dputs(const char *str)

{

while(*str != 0) {

_dputc(*str++);

}

return 0;

}



mediatek/platform/mt6572/lk/debug.c

#include <debug.h>

#include <kernel/thread.h>

#include <stdarg.h>

#include <dev/uart.h>

#include <platform/mt_uart.h>

void
_dputc(char c)

{

if (c == '\n')

uart_putc('\r');

uart_putc(c);// 这个函数便是最终发送字符到串口的函数。它位于LK的串口驱动(mediatek/platform/mt6572/lk/uart.c)中。

}



// mediatek/platform/mt6572/kernel/drivers/uart/mt_fiq_debugger.c: .uart_putc = &fiq_uart_putc,

// mediatek/platform/mt6572/lk/uart.c:int uart_putc(const char c )





mediatek/platform/mt6572/lk/uart.c

int
uart_putc(const char c )

{

while (!(DRV_Reg32(UART_LSR(g_uart)) & UART_LSR_THRE));// 读取并判断串口当前的状态,如果忙,就一直轮训,如果不忙,就跳到下面的代码执行,把要发送的字符写入到发送的寄存器UART_THR。

if (c == '\n')

mt65xx_reg_sync_writel((unsigned int)'\r', UART_THR(g_uart));

mt65xx_reg_sync_writel((unsigned int)c, UART_THR(g_uart));

return 0;

}













/*

FILENAME: bootable/bootloader/lk/lib/libc/printf.c

* Copyright (c) 2008 Travis Geiselbrecht

*

* Permission is hereby granted, free of charge, to any person obtaining

* a copy of this software and associated documentation files

* (the "Software"), to deal in the Software without restriction,

* including without limitation the rights to use, copy, modify, merge,

* publish, distribute, sublicense, and/or sell copies of the Software,

* and to permit persons to whom the Software is furnished to do so,

* subject to the following conditions:

*

* The above copyright notice and this permission notice shall be

* included in all copies or substantial portions of the Software.

*

* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,

* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF

* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.

* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY

* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,

* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE

* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

#include <debug.h>

#include <limits.h>

#include <stdarg.h>

#include <sys/types.h>

#include <printf.h>

#include <string.h>

void putc(char c)

{

return _dputc(c);

}

int puts(const char *str)

{

return _dputs(str);

}

int getc(char *c)

{

return dgetc(c, true);

}

int printf(const char *fmt, ...)

{

int err;

va_list ap;

va_start(ap, fmt);

err = _dvprintf(fmt, ap);

va_end(ap);

return err;

}

int sprintf(char *str, const char *fmt, ...)

{

int err;

va_list ap;

va_start(ap, fmt);

err = vsprintf(str, fmt, ap);

va_end(ap);

return err;

}

int snprintf(char *str, size_t len, const char *fmt, ...)

{

int err;

va_list ap;

va_start(ap, fmt);

err = vsnprintf(str, len, fmt, ap);

va_end(ap);

return err;

}

#define LONGFLAG 0x00000001

#define LONGLONGFLAG 0x00000002

#define HALFFLAG 0x00000004

#define HALFHALFFLAG 0x00000008

#define SIZETFLAG 0x00000010

#define ALTFLAG 0x00000020

#define CAPSFLAG 0x00000040

#define SHOWSIGNFLAG 0x00000080

#define SIGNEDFLAG 0x00000100

#define LEFTFORMATFLAG 0x00000200

#define LEADZEROFLAG 0x00000400

static char *longlong_to_string(char *buf, unsigned long long n, int len, uint flag)

{

int pos = len;

int negative = 0;

if((flag & SIGNEDFLAG) && (long long)n < 0) {

negative = 1;

n = -n;

}

buf[--pos] = 0;



/* only do the math if the number is >= 10 */

while(n >= 10) {

int digit = n % 10;

n /= 10;

buf[--pos] = digit + '0';

}

buf[--pos] = n + '0';



if(negative)

buf[--pos] = '-';

else if((flag & SHOWSIGNFLAG))

buf[--pos] = '+';

return &buf[pos];

}

static char *longlong_to_hexstring(char *buf, unsigned long long u, int len, uint flag)

{

int pos = len;

static const char hextable[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

static const char hextable_caps[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

const char *table;

if((flag & CAPSFLAG))

table = hextable_caps;

else

table = hextable;

buf[--pos] = 0;

do {

unsigned int digit = u % 16;

u /= 16;



buf[--pos] = table[digit];

} while(u != 0);

return &buf[pos];

}

int vsprintf(char *str, const char *fmt, va_list ap)

{

return vsnprintf(str, INT_MAX, fmt, ap);

}

int vsnprintf(char *str, size_t len, const char *fmt, va_list ap)

{

char c;

unsigned char uc;

const char *s;

unsigned long long n;

void *ptr;

int flags;

unsigned int format_num;

size_t chars_written = 0;

char num_buffer[32];

#define OUTPUT_CHAR(c) do { (*str++ = c); chars_written++; if (chars_written + 1 == len) goto done; } while(0)

#define OUTPUT_CHAR_NOLENCHECK(c) do { (*str++ = c); chars_written++; } while(0)

for(;;) {

/* handle regular chars that aren't format related */

while((c = *fmt++) != 0) {

if(c == '%')

break; /* we saw a '%', break and start parsing format */

OUTPUT_CHAR(c);

}

/* make sure we haven't just hit the end of the string */

if(c == 0)

break;

/* reset the format state */

flags = 0;

format_num = 0;

next_format:

/* grab the next format character */

c = *fmt++;

if(c == 0)

break;



switch(c) {

case '0'...'9':

if (c == '0' && format_num == 0)

flags |= LEADZEROFLAG;

format_num *= 10;

format_num += c - '0';

goto next_format;

case '.':

/* XXX for now eat numeric formatting */

goto next_format;

case '%':

OUTPUT_CHAR('%');

break;

case 'c':

uc = va_arg(ap, unsigned int);

OUTPUT_CHAR(uc);

break;

case 's':

s = va_arg(ap, const char *);

if(s == 0)

s = "<null>";

goto _output_string;

case '-':

flags |= LEFTFORMATFLAG;

goto next_format;

case '+':

flags |= SHOWSIGNFLAG;

goto next_format;

case '#':

flags |= ALTFLAG;

goto next_format;

case 'l':

if(flags & LONGFLAG)

flags |= LONGLONGFLAG;

flags |= LONGFLAG;

goto next_format;

case 'h':

if(flags & HALFFLAG)

flags |= HALFHALFFLAG;

flags |= HALFFLAG;

goto next_format;

case 'z':

flags |= SIZETFLAG;

goto next_format;

case 'D':

flags |= LONGFLAG;

/* fallthrough */

case 'i':

case 'd':

n = (flags & LONGLONGFLAG) ? va_arg(ap, long long) :

(flags & LONGFLAG) ? va_arg(ap, long) :

(flags & HALFHALFFLAG) ? (signed char)va_arg(ap, int) :

(flags & HALFFLAG) ? (short)va_arg(ap, int) :

(flags & SIZETFLAG) ? va_arg(ap, ssize_t) :

va_arg(ap, int);

flags |= SIGNEDFLAG;

s = longlong_to_string(num_buffer, n, sizeof(num_buffer), flags);

goto _output_string;

case 'U':

flags |= LONGFLAG;

/* fallthrough */

case 'u':

n = (flags & LONGLONGFLAG) ? va_arg(ap, unsigned long long) :

(flags & LONGFLAG) ? va_arg(ap, unsigned long) :

(flags & HALFHALFFLAG) ? (unsigned char)va_arg(ap, unsigned int) :

(flags & HALFFLAG) ? (unsigned short)va_arg(ap, unsigned int) :

(flags & SIZETFLAG) ? va_arg(ap, size_t) :

va_arg(ap, unsigned int);

s = longlong_to_string(num_buffer, n, sizeof(num_buffer), flags);

goto _output_string;

case 'p':

flags |= LONGFLAG | ALTFLAG;

goto hex;

case 'X':

flags |= CAPSFLAG;

/* fallthrough */

hex:

case 'x':

n = (flags & LONGLONGFLAG) ? va_arg(ap, unsigned long long) :

(flags & LONGFLAG) ? va_arg(ap, unsigned long) :

(flags & HALFHALFFLAG) ? (unsigned char)va_arg(ap, unsigned int) :

(flags & HALFFLAG) ? (unsigned short)va_arg(ap, unsigned int) :

(flags & SIZETFLAG) ? va_arg(ap, size_t) :

va_arg(ap, unsigned int);

s = longlong_to_hexstring(num_buffer, n, sizeof(num_buffer), flags);

if(flags & ALTFLAG) {

OUTPUT_CHAR('0');

OUTPUT_CHAR((flags & CAPSFLAG) ? 'X': 'x');

}

goto _output_string;

case 'n':

ptr = va_arg(ap, void *);

if(flags & LONGLONGFLAG)

*(long long *)ptr = chars_written;

else if(flags & LONGFLAG)

*(long *)ptr = chars_written;

else if(flags & HALFHALFFLAG)

*(signed char *)ptr = chars_written;

else if(flags & HALFFLAG)

*(short *)ptr = chars_written;

else if(flags & SIZETFLAG)

*(size_t *)ptr = chars_written;

else

*(int *)ptr = chars_written;

break;

default:

OUTPUT_CHAR('%');

OUTPUT_CHAR(c);

break;

}

/* move on to the next field */

continue;

/* shared output code */

_output_string:

if (flags & LEFTFORMATFLAG) {

/* left justify the text */

uint count = 0;

while(*s != 0) {

OUTPUT_CHAR(*s++);

count++;

}

/* pad to the right (if necessary) */

for (; format_num > count; format_num--)

OUTPUT_CHAR(' ');

} else {

/* right justify the text (digits) */

size_t string_len = strlen(s);

char outchar = (flags & LEADZEROFLAG) ? '0' : ' ';

for (; format_num > string_len; format_num--)

OUTPUT_CHAR(outchar);

/* output the string */

while(*s != 0)

OUTPUT_CHAR(*s++);

}

continue;

}

done:

/* null terminate */

OUTPUT_CHAR_NOLENCHECK('\0');

chars_written--; /* don't count the null */

#undef OUTPUT_CHAR

#undef OUTPUT_CHAR_NOLENCHECK

return chars_written;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: