歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> ARM 平台printf函數定位到uart輸出介紹

ARM 平台printf函數定位到uart輸出介紹

日期:2017/3/1 10:19:55   编辑:Linux編程

1.1 ARM 串口輸出函數uart_printf

ARM如果能使用C函數庫自帶的printf函數格式輸出,那多方便,但是默認的printf都是定位到stdout終端,而不是串口,本文章講述的是如何定位到ARM的串口。

1.1.1 函數主要代碼

有在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> //需要包含此stdarg.h頭文件

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

#defineRXD0READY (1)

#definePCLK 50000000 // init.c中的clock_init函數設置PCLK為50MHz

#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);//端口配置成uart0、uart1,uart3

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);

}

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

1.1.2 uart_printf分析

這裡涉及到一個重要概念,變參函數,比如C庫函數int printf(char *fmt, ...),就是一個典型的變參函數。

我們即將編寫的uart_printf毫無疑問,也是一個變參函數。

可變參數入棧順序

在進程中,堆棧地址是從高到低分配的.當執行一個函數的時候,將參數列表入棧,壓入堆棧的高地址部分,然後入棧函數的返回地址,接著入棧函數的執行代碼,這個入棧過程,堆棧地址不斷遞減,一些黑客就是在堆棧中修改函數返回地址,執行自己的代碼來達到執行自己插入的代碼段的目的.

總之,函數在堆棧中的分布情況是:地址從高到低,依次是:函數參數列表,函數返回地址,函數執行代碼段.

堆棧中,各個函數的分布情況是倒序的.即最後一個參數在列表中地址最高部分,第一個參數在列表地址的最低部分.參數在堆棧中的分布情況如下:

  最後一個參數

  倒數第二個參數

  ...

  第一個參數

  函數返回地址

  函數代碼段

Copyright © Linux教程網 All Rights Reserved