DSP

DSP下面printf串口输出的实现

2019-07-13 09:57发布

      前段时间在一个DSP上做音视频解码,没有操作系统 ,调试的时候又不能用仿真器狂打断点,不然同步逻辑跟时间相关不好调试,逼得自己写了个串口printf,现在把它整理出来。原来觉得printf的可变参数多神秘,这下算又搞清楚一些了。 #define swap(x, y) 
{   
      asm( 
"swap %1, %0" 
      : 
"+r" (*(x)), "+r" (*(y))); 


unsigned 
char printf_buffer[50= {0};
#define MOD(x, y) ((x) - (y) * ((unsigned long)(x) / (unsigned long)(y)))

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

void number(unsigned char* dst, unsigned long *offset, 
            
long num, int base)
{
    
long remain, i, len;
    unsigned 
long start;
    unsigned 
long end;

    
if (num < 0)
    {
        num 
= -num;
        dst[(
*offset)++= '-';
    }
    
    start 
= *offset;
    
while (num >= 0)
    {
        dst[(
*offset)++= alphabet[MOD(num, base)];
        remain 
= num / base;
        num 
= remain;
        
if (num == 0)
            
break;
    }
    end 
= *offset - 1;
    len 
= ((end - start) + 1/ 2;
    
    
for (i = 0; i < len; i++)
        swap(dst 
+ start + i, dst + end -i);
}

int myprintf(const char* fmt, ...)
{
    va_list args;
    unsigned 
long i = 0;
    
char* s; 
    
    va_start(args, fmt);
    
    
while (*fmt)
    {
        
if (*fmt == '%')
        {
            fmt
++;
            
switch (*fmt)
            {
                
case 'd':
                    number(printf_buffer, 
&i, va_arg(args, int), 10);
                    
break;
                
case 'l':
                    number(printf_buffer, 
&i, va_arg(args, long), 10);
                    
break;
                
case 'x':
                    number(printf_buffer, 
&i, va_arg(args, long), 16);
                    
break;
                
case 's':
                     s 
= va_arg(args, char*);
                     
while (*s)
                     {
                         printf_buffer[i
++= *s++;
                     }
                    
                    
break;
                
default:
                    
break;
            }
            fmt
++;
        }
        
else 
        {
            printf_buffer[i
++= *fmt++;
        }
    }
    va_end(args);
    printf_buffer[i++] = '/0';
   
   
return uart_send((const char*)printf_buffer);
}
uart_send 是串口驱动提供的发送函数. 编译器在调用函数的时候会把可变参数依次压入fmt参数后面,va_start将args赋值为fmt后一个地址,然后根据fmt里面的描述在适当的时候,依次用va_arg取得可变参数并改变args的值使其指向下一个参数的地址。