DSP

最近在TI的e2e以及相关QQ群众讨论时很多同学在做DSP算法或者在使用中断时SYS/BIOS被异常

2019-07-13 19:34发布

 最近在TI的e2e以及相关QQ群众讨论时很多同学在做DSP算法或者在使用中断时SYS/BIOS被异常挂起,最终分析下来的原因是因为在中断上下文中使用了Vps_printf()或者是在禁止中断后恢复中断前的期间内使用了Vps_printf(),即hwi_disable()和hwi_restore()的上下文中使用。        在TI提供的RDK(包括DVRRDK和IPNCRDK)中Ducati-M3和DSP中运行的实时操作系统为SYS/BIOS,在SYS/BIOS中输出到串口的打印API为System_printf()。提供的能输出到linux串口的API即为Vps_printf()和Vps_rprintf()。        下面我们来分析下Vps_printf()和Vps_rprintf的源代码和相关限制。        首先我们来看下两个API的实现代码: [cpp] view plaincopy
  1. int Vps_printf(char *format, ...)  
  2. {  
  3.     int retVal;  
  4.     va_list vaArgPtr;  
  5.     char *buf = NULL;  
  6.     UInt32 cookie;  
  7.   
  8.     cookie = Hwi_disable();  
  9.   
  10.     buf = &gRemoteDebug_serverObj.printBuf[0];  
  11.   
  12.     va_start(vaArgPtr, format);  
  13.     vsnprintf(buf, REMOTE_DEBUG_SERVER_PRINT_BUF_LEN, format, vaArgPtr);  
  14.     va_end(vaArgPtr);  
  15.   
  16.     retVal = RemoteDebug_serverPutString(gRemoteDebug_serverObj.coreId, buf);  
  17.   
  18.     Hwi_restore(cookie);  
  19.   
  20.     if (BIOS_getThreadType() == BIOS_ThreadType_Task)  
  21.     {  
  22.         /* Printf should be called only from Task context as it does pend. 
  23.          * Calling from other context will cause exception 
  24.          */  
  25.         System_printf(buf);  
  26.     }  
  27.   
  28.     return (retVal);  
  29. }  
[cpp] view plaincopy
  1. int Vps_rprintf(char *format, ...)  
  2. {  
  3.     int retVal;  
  4.     va_list vaArgPtr;  
  5.     char *buf = NULL;  
  6.     UInt32 cookie;  
  7.   
  8.     cookie = Hwi_disable();  
  9.   
  10.     buf = &gRemoteDebug_serverObj.printBuf[0];  
  11.   
  12.     va_start(vaArgPtr, format);  
  13.     vsnprintf(buf, REMOTE_DEBUG_SERVER_PRINT_BUF_LEN, format, vaArgPtr);  
  14.     va_end(vaArgPtr);  
  15.   
  16.     retVal = RemoteDebug_serverPutString(gRemoteDebug_serverObj.coreId, buf);  
  17.   
  18.     Hwi_restore(cookie);  
  19.   
  20.     return (retVal);  
  21. }  
       由上面两端代码可以很明显的看出Vps_printf()和Vps_rprintf()的前半部分都是讲输出到共享内存中供A8侧打印线程输出,唯一的区别就是Vps_printf()会判断当前thread类型是否是Task,如果是Task则调用SYS/BIOS下的System_printf(),将数据输出到对应处理器的串口或者是Circular Buffer中。        在Vps_printf()中有下列注释: [cpp] view plaincopy
  1. /* Printf should be called only from Task context as it does pend. 
  2.  * Calling from other context will cause exception 
  3.  */  
即表示Vps_printf()只能被用于Task任务类型的thread,在其他类型的thread中会导致异常情况。(thread未翻译成线程,因为这里的thread和我们通常理解的线程有差异)
      此外,需要注意的是在Vps_printf()和Vps_rprintf()的实现中均需要屏蔽硬件中断,因此不能用于硬件中断类型的thread。下面有个童鞋使用的错误的例子:

注: 1、在SYS/BIOS下线程可以分为以下几类,如下图所示: 2、SYS/BIOS下的System_printf()可以配制成两种模式,一种是输出到串口,另一种是将内容输出到SYS/BIOS下配置的静态circular buffer中。System_printf()的静态circular buffer配置及输出方式配置如下图所示: