设为首页 加入收藏

TOP

ARM 平台printf函数定位到uart输出介绍
2014-11-24 12:25:49 来源: 作者: 【 】 浏览:0
Tags:ARM 平台 printf 函数定位 uart 输出 介绍

ARM如果能使用C函数库自带的printf函数格式输出,那多方便,但是默认的printf都是定位到stdout终端,而不是串口,本文章讲述的是如何定位到ARM的串口。


有在Mini2440开发板上验证过


//*****************main.c*******************************


#include"serial.h"


int Main()


{


unsignedint plck_val = 50000000;


unsignedint buad_val = 115200;


unsignedint ch_val = 0;


char*string="Hello,http://blog.csdn.net/wfq0624";


uart_init();


uart_printf("\n\r%s\n",string);


uart_printf("\rUse uart0\n\rParameter:PCLK is %d,buad is %d,uart_port is %d \n",plck_val,buad_val,ch_val);


uart_printf("\r该函数不能打印浮点数!");


return 0;


}


//***********************serial.c**************************


#include"s3c2440.h"


#include"serial.h"


#include //需要包含此stdarg.h头文件


#include //需要包涵此stdio.h头文件
#define TXD0READY (1<<2)


#defineRXD0READY (1)



#definePCLK 50000000 // init.c中的clock_init函数设置PCLK50MHz


#defineUART_CLK PCLK // UART0的时钟源设为PCLK


#defineUART_BAUD_RATE 115200 // 波特率


#defineUART_BRD ((UART_CLK / (UART_BAUD_RATE * 16)) - 1)


voiduart_init()


{ //UART初始化:端口使能、功能设定、波特率、设置数据格式


GPHCON = (GPHCON & ~(0xfff<<4)) |(0xaaa<<4);//端口配置成uart0uart1uart3


GPHUP = 0x38; //端口GPH禁止上拉


UFCON0 = 0x0; //禁止FIFO


UMCON0 = 0x0; //禁止AutoFlow Control


//Normal:No parity:One stop:8-bits 中断响应 UART clock: PCLK


ULCON0 = 0x03; // 8N1(8个数据位,无较验,1个停止位)


UCON0 = 0x05; // 查询方式,UART时钟源为PCLK


UBRDIV0 = UART_BRD; // 波特率为115200


}



voiduart_send_byte(char data)


{


while (!(UTRSTAT0 & TXD0READY));


UTXH0 = data;


}


voiduart_send_string(char *string)


{


while(*string)


{


uart_send_byte(*string++);


}


}


void uart_printf(char *fmt,...) //这个才是本文重点


{


va_listap;


charstring[256];


va_start(ap,fmt);


vsprintf(string,fmt,ap);


uart_send_string(string);


va_end(ap);


}


//***************************************************


这里涉及到一个重要概念,变参函数,比如C库函数int printf(char *fmt, ...),就是一个典型的变参函数。


我们即将编写的uart_printf毫无疑问,也是一个变参函数。



可变参数入栈顺序


在进程中,堆栈地址是从高到低分配的.当执行一个函数的时候,将参数列表入栈,压入堆栈的高地址部分,然后入栈函数的返回地址,接着入栈函数的执行代码,这个入栈过程,堆栈地址不断递减,一些黑客就是在堆栈中修改函数返回地址,执行自己的代码来达到执行自己插入的代码段的目的.


总之,函数在堆栈中的分布情况是:地址从高到低,依次是:函数参数列表,函数返回地址,函数执行代码段.


堆栈中,各个函数的分布情况是倒序的.即最后一个参数在列表中地址最高部分,第一个参数在列表地址的最低部分.参数在堆栈中的分布情况如下:


  最后一个参数


  倒数第二个参数


  ...


  第一个参数


  函数返回地址


  函数代码段


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇iOS非ARC内存管理摘要 下一篇jQuery动态添加和删除class属性

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·数据库:推荐几款 Re (2025-12-25 12:17:11)
·如何最简单、通俗地 (2025-12-25 12:17:09)
·什么是Redis?为什么 (2025-12-25 12:17:06)
·对于一个想入坑Linux (2025-12-25 11:49:07)
·Linux 怎么读? (2025-12-25 11:49:04)