⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uart.c

📁 自己编写的bootloader for S3c4510. 1、支持串口下载
💻 C
字号:
#include "Main.h"

void UART_init(unsigned int ch,unsigned int baud)
{
     if(ch)
     {
          UARTLCON1=0x3;     // 8-bit no pariy 1 stop-bit
          UARTCONT1=0x9;     // rx/tx interrupt
          UARTBRD1 =((int)(MCLK_MHz/(baud<<5)))<<4;  
     }
     else 
     {
          UARTLCON0=0x3;
          UARTCONT0=0x9;
          UARTBRD0 =((int)(MCLK_MHz/(baud<<5)))<<4;  //(int)(MCLK/(32*baud)-1);
     	  Enable_Int(nUART0_RX_ERR_INT);
     }
     init_queue(&Uart_buffer);
}
//-***********************************************-//
//    串口发送出一个字符串
//-***********************************************-//
void Print_URAT(int port,char *s)
{
     if(port==0)
     for(;*s!='\0';s++)
     {
         for(;(!(UARTSTAT0&0x40)););
         UARTTXH0=*s;   
     }
     else if(port==1)
     for(;*s!='\0';s++)
     {
         for(;(!(UARTSTAT1&0x40)););
         UARTTXH1=*s;   
     }
}

/* printp() ------------ a simply version of printf()                */


/*修改了部分printp()代码,
 打印时如果 %后面的x,d为大写,打印的数不区分正负数
                      为小写,区分正负数
                 加l为取长型变量。

例如打印如下语句:

	printp("\n here i is 0xF123ABCD, j is 0xF123");
	printp("\n 1 : %%X i is: %X",i);
	printp("\n 2 : %%x i is: %x",i);
	printp("\n 3 : %%D i is: %D",i);
	printp("\n 4 : %%d i is: %d",i);
	printp("\n 5 : %%X j is: %X",j);
	printp("\n 6 : %%x j is: %x",j);
	printp("\n 7 : %%D j is: %D",j);
	printp("\n 8 : %%d j is: %d",j);
结果为:
	 here i is 0xF123ABCD, j is 0xF123
	 1 : %X i is: F123ABCD
	 2 : %x i is: -EDC5433
	 3 : %D i is: 4045646797
	 4 : %d i is: -249320499
	 5 : %X j is: F123
	 6 : %x j is: F123
	 7 : %D j is: 61731
	 8 : %d j is: 61731  */
 
/************************************************************************/


#define CR_as_CRLF  TRUE             // if true , you can use "\n" to act as CR/LF, 
                                     // if false , you have to use "\n\r",but can get a higher speed



void uart_putchar(unsigned char ch)
{
  for(;(!(UARTSTAT0&0x40)););
         UARTTXH0=ch;
}

static int do_padding;
static int left_flag;
static int len;
static int num1;
static int num2;
static char pad_character;

/*---------------------------------------------------*/
/*                                                   */
/* This routine puts pad characters into the output  */
/* buffer.                                           */
/*                                                   */
static void padding( const int l_flag)
{
   int i;

   if (do_padding && l_flag && (len < num1))
      for (i=len; i<num1; i++)
          uart_putchar( pad_character);
   }

/*---------------------------------------------------*/
/*                                                   */
/* This routine moves a string to the output buffer  */
/* as directed by the padding and positioning flags. */
/*                                                   */
static void outs( char* lp)
{
   /* pad on left if needed                          */
   len = strlen( lp);
   padding( !left_flag);

   /* Move string to the buffer                      */
   while (*lp && num2--)
      uart_putchar( *lp++);

   /* Pad on right if needed                         */
   len = strlen( lp);
   padding( left_flag);
   }

/*---------------------------------------------------*/
/*                                                   */
/* This routine moves a number to the output buffer  */
/* as directed by the padding and positioning flags. */
/*                                                   */
static void reoutnum(unsigned long num, unsigned int negative, const long base ) 
{
   char* cp;
   char outbuf[32];
   const char digits[] = "0123456789ABCDEF";
   
   /* Build number (backwards) in outbuf             */
   cp = outbuf;
   do {
      *cp++ = digits[(int)(num % base)];
      } while ((num /= base) > 0);
   if (negative)
      *cp++ = '-';
   *cp-- = 0;

   /* Move the converted number to the buffer and    */
   /* add in the padding where needed.               */
   len = strlen(outbuf);
   padding( !left_flag);
   while (cp >= outbuf)
      uart_putchar( *cp--);
   padding( left_flag);
}


static void outnum(long num, const long base ,unsigned char sign)//1, signed  0 unsigned
{   unsigned int negative;

   if ( (num < 0L) && sign ) 
   {  negative=1;
      num = -num;
      }
   else negative=0;
   
   reoutnum(num,negative,base);  
} 
/*---------------------------------------------------*/
/*                                                   */
/* This routine gets a number from the format        */
/* string.                                           */
/*                                                   */
static int getnum( char** linep)
{
   int n;
   char* cp;

   n = 0;
   cp = *linep;
   while (isdigit(*cp))
      n = n*10 + ((*cp++) - '0');
   *linep = cp;
   return(n);
}

/*---------------------------------------------------*/
/*                                                   */
/* This routine operates just like a printf/sprintf  */
/* routine. It outputs a set of data under the       */
/* control of a formatting string. Not all of the    */
/* standard C format control are supported. The ones */
/* provided are primarily those needed for embedded  */
/* systems work. Primarily the floaing point         */
/* routines are omitted. Other formats could be      */
/* added easily by following the examples shown for  */
/* the supported formats.                            */
/*                                                   */

void printp( char* ctrl, ...)
{

   int long_flag;
   int dot_flag;

   char ch;
   va_list argp;		//由于为可变参数函数,需要进行参数提取;argp依次批向各可变参数

   va_start( argp, ctrl);//初始化argp,使它指向第一个参数

   for ( ; *ctrl; ctrl++) 
   {
      /* move format string chars to buffer until a  */
      /* format control is found.                    */
      if (*ctrl != '%') 
      {
         uart_putchar(*ctrl);
		 #if CR_as_CRLF==TRUE         
         if(*ctrl=='\n') uart_putchar('\r');
         #endif         
         continue;
      }
      /* initialize all the flags for this format.   */
      dot_flag   =
      long_flag  =
      left_flag  =
      do_padding = 0;
      pad_character = ' ';
      num2=0x7fffffff;

try_next:
      ch = *(++ctrl);

      if (isdigit(ch)) 
      {
         if (dot_flag)
            num2 = getnum(&ctrl);
         else {
            if (ch == '0')
               pad_character = '0';

            num1 = getnum(&ctrl);
            do_padding = 1;
         }
         ctrl--;
         goto try_next;
      }

      switch (ch) 
      {
         case '%':
              uart_putchar( '%');
              continue;

         case '-':
              left_flag = 1;
              break;

         case '.':
              dot_flag = 1;
              break;

         case 'd':
                        outnum( va_arg(argp, int), 10,1);
              		    continue;
         case 'D':

              		    outnum( va_arg(argp, unsigned int),10,0);
              		    continue;

         case 'x':    // X 无符号 , x  有符号
                        outnum( va_arg(argp, int), 16 ,1);
              		    continue;
         case 'X':
              		    outnum( va_arg(argp, unsigned int), 16 ,0);
              		    continue;

                 //如果按照16进制打印,将全部按照无符号数进行
                    continue;

         case 's':
               outs( va_arg( argp, char*));
               continue;

         case 'c':
              uart_putchar((char)va_arg( argp, int));
              continue;

         default:
              continue;
      }
      goto try_next;
   }
   va_end( argp);
}
/*
How to use variable argument function
C语言支持va函数,作为C语言的扩展--C++同样支持va函数,但在C++中并不推荐使用,
C++引入的多态性同样可以实现参数个数可变的函数。不过,C++的重载功能毕竟只能
是有限多个可以预见的参数个数。比较而言,C中的va函数则可以定义无穷多个相当于
C++的重载函数,这方面C++是无能为力的。va函数的优势表现在使用的方便性和易用
性上,可以使代码更简洁。C编译器为了统一在不同的硬件架构、硬件平台上的实现,
和增加代码的可移植性,提供了一系列宏来屏蔽硬件环境不同带来的差异。

 
ANSI C标准下,va的宏定义在stdarg.h中,它们有:va_list,va_start(),va_arg(),va_end()。 

 
 
va_list arg_ptr:定义一个指向个数可变的参数列表指针;

va_start(arg_ptr, argN):使参数列表指针arg_ptr指向函数参数列表中的第一个可选参数,
说明:argN是位于第一个可选参数之前的固定参数,(或者说,最后一个固定参数;…之前的一个参数)
,函数参数列表中参数在内存中的顺序与函数声明时的顺序是一致的。如果有一va函数的声明是
void va_test(char a, char b, char c, …),则它的固定参数依次是a,b,c,最后一个固定参数argN为c,
因此就是va_start(arg_ptr, c)。

va_arg(arg_ptr, type):返回参数列表中指针arg_ptr所指的参数,返回类型为type,并使指针arg_ptr
指向参数列表中下一个参数。

va_copy(dest, src):dest,src的类型都是va_list,va_copy()用于复制参数列表指针,将dest初始化为src。

va_end(arg_ptr):清空参数列表,并置参数指针arg_ptr无效。说明:指针arg_ptr被置无效后,可以
通过调用va_start()、va_copy()恢复arg_ptr。每次调用va_start() / va_copy()后,必须得有相应
的va_end()与之匹配。参数指针可以在参数列表中随意地来回移动,但必须在va_start() … va_end()之内。
*/
char get_char(unsigned int channel) 
{ 
    char ch;
    if(channel) 
    { 
    	while(!(UARTSTAT1 & USTAT_RCV_READY))
        ch = UARTRXB1;
    }
    else 
    { 
    	while(!(UARTSTAT0 & USTAT_RCV_READY))
        ch = UARTRXB0;
    }
    return ch;
}
void Uart0_R_interrupt(void)
{
    char ch;
    ch = UARTRXB0;
    if(command_flag == TRUE)
    { 
      if(Enqueue(&Uart_buffer,ch) == FALSE)
      printp("\n Uart_buffer is full!");
    }
    else
    {
      *Puart_receiver_buffer++ = ch;
      printp("%x  ",ch);
      uart_receiver_count++;
      if(!(uart_receiver_count%5000)) printp("*");
      Uart_receiving_file = TRUE;
      Time0_count = 0;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -