This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] RTOS/CC2650STK:如何使用'Log_Info1 %s 和#39;?

Guru**** 2611705 points
Other Parts Discussed in Thread: CC2650, CC2650STK, SYSBIOS

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/581745/rtos-cc2650stk-how-can-i-use-log_info1-s

器件型号:CC2650STK
Thread 中讨论的其他部件:CC2650SYSBIOS

工具/软件:TI-RTOS

您好 TI 团队

我有一个问题。

我使用 Log_Info1函数、但%s 不是 UART 日志打印

如何使用日志%s?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 Kevin:

    您使用的是什么记录器?

    谢谢、
    Gerardo
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Gerardo Gomez Martinez,

    UART_LOGS 和 XDC 日志

    主板 CC2650STK 和 CC2650_launchpad

    UART_LOGS 中的 CC2650_lanchpad 基本源代码'Project Zero'合并到 CC2650_sensortag

    基本 IDE:CCS 7.0

    include 文件
    #include

    包含 app_ble.cfg 源文件


    //剩余模块
    VAR 诊断= xdc.useModule('xdc.runtime.Diags');
    VAR Main = xdc.useModule('xdc.runtime.Main');
    VAR Reset = xdc.useModule('xdc.runtime.Reset');




    //需要为 Log_info/warning/error 格式加载文本,但不为 Log_print 加载文本。
    text.isLoaded = true;

    //日志记录
    VAR 日志= xdc.useModule('xdc.runtime.Log');

    //用 ANSI 代码覆盖错误输出颜色,并使用更短的(file.c:line)格式。
    log.L_error ={
    mask:diags.status、
    级别:diags.error、
    MSG:"\x1b[31;1mERROR:\x1b[0m (%s:%d)%$S"
    };

    log.L_info ={
    mask:diags.info、
    MSG:"\x1b[32;1mINFO:\x1b[0m (%s:%d)%$S"
    };

    log.L_warning ={
    mask:diags.status、
    级别:diags.warning、
    MSG:"\x1b[33;1mWARNING:\x1b[0m (%s:%d)%$S"
    };

    //拉入 LoggerCallback
    VAR LoggerCallback = xdc.useModule('xdc.runtime.LoggerCallback');

    //让 LoggerCallback 调用我们的输出函数
    LoggerCallback.outputFxn ="&uartLog_outputFxn";

    //告诉空闲模块将 flush()函数添加到空闲循环(在通电之前)
    VAR Idle = xdc.useModule('ti.sysbios.knl.Idle');//如果空闲尚未导入则添加。
    idle.addFunc ('&uartLog_flush');

    //创建 LoggerCallback 的静态实例并设置为默认主记录器
    var logerParams = new LoggerCallback.Params();
    logerParams.arg = 1;

    //仅适用于 Main (不在 rtsc 模块中的代码)
    Main.common$.logger = LoggerCallback.create (loggerParams);
    //Defaults.common$.logger = LoggerCallback.create (loggerParams);//用于所有日志事件

    //打开主模块中的 User1日志和信息(用户代码)。 关闭 User2以获得乐趣。
    Main.common$.diags_USER1 = Diags.always_on;
    Main.common$.diags_USER2 = Diags.always_off;
    Main.common$.diags_USER6 = Diags.always_on;
    Main.common$.diags_INFO = Diags.always_on;

    如何使用'Log_Info1 ("aaa1=[%s]",a);'?

    感谢您的回复、

    此致。

    Kevin。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Kevin、
    我们能看到您的 uartLog_outputFxn 吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    此处为 uartLog_outputFxn 函数中的 UART_logs.c 




    /********* *@fn uartLog_outputFxn * *@简单用户提供的 LoggerCallback 输出函数。 * typedef void (* LoggerCallback_OutputFxn)(UArg, Log_EventRec*,Int); * 每当 LoggerCallback 模块需要 *时、都会调用此函数 以输出日志事件。 * * 此实现使用日志记录 *填充非常基本的环形缓冲区 相对较低的开销、并且依赖于另一个函数 来* 将日志记录转换为文本并在 UART 上传输字符串。 * * 需要 LoggerCallback 作为 ILogger 提供程序模块。 * 通过 LoggerCallback.outputFxn 初始化="&uartLog_outputFxn"; * 配置脚本中的代码。 * * 请注意、也必须包含日志才能使用接口、和 * 必须创建 LoggerCallback 实例并将其指定为默认值。 * 因此、总的来说: * VAR Log = xdc.useModule('xdc.runtime.Log'); * VAR LoggerCallback = xdc.useModule('xdc.runtime.LoggerCallback'); * LoggerCallback.outputFxn ="&uartPrintf_logOutputFxn"; * var logerParams = new LoggerCallback.Params(); * Defaults.common$.logger = LoggerCallback.create (loggerParams); * @param a0 -创建 LoggerCallback 记录器时用户提供的参数。 * 精密- LoggerCallback 创建的 Log_EventRec 的指针 * numArgs -精密中使用的参数数。 * *@返回无。 * *@POST ::uartLog_head 递增,如果它等于_tail ,* 两者一起移动,丢弃最早的记录。 */ void althic uartLog_outputFxn (UArg0、Log_EventRec *精密、Int32_t numArgs){#if (defined (XDC_RUNITY_LOG_DISABLE_ALL)&&(XDC_RUNITY_Log_DISABLE_ALL = 0)|!!defined (XDC_RUNITY_LOG_LOG_RECORD = 0)*= 0)+ UARTHETOOT_TOOT_TOOT_0*= 0)*/ UTOOTH = 0 (UTOOTH = 0)*/ UTOOTH = 0)* 0)+ UARTHET = UTOOT_TOOT_TOOTH = 0)*= 0 (UTOOTH = 0 /*如果 精密 Log_EvtRec */ uartLog_evBuf[uartLog_head].tstamp_cust = AONRTCCurrentCompareValueGet ();uartLog_evBuf[uartLog_head].serial_cust = uartLog_evtNum;uartLog_evt_eLog+[uarture_e*/uarteude*=uart_eveLog_e*=uarte*=uarte*=uarte*/eude&e&eude*=uarte&e&eude*=uarte&e&e&e&e&e&e&e&e&;uarteudeude&e&e&eude&;uarteude&e&e&e&;e&;e&;e&;e 精密->参数、 sizeof (__TA_XDC_Runtime_Log_EventRec__arg);//复制日志参数*// *如果缓冲区已满,则丢弃最旧的*/ if (!uartLog_evBufIsEmpty &&(uartLog_head == uartLog_tail)) ){ moveTail = 1; } //以环绕方式增加头数*/ uartLog_head += 1; if (uartLog_head == UARTLOG_NUM_EVT_BUF) { uartLog_head = 0; } if (moveTail) { uartLog_tail = uartLog_head; } //这用于识别 head=tail 是指空还是满*/ uartLog_evBufIsEmpty = false; //让 mayhem 开始*/ Hwi_restore (key); #endif };

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我忘了询问 uartlof flush。 这是解释和显示事件的地方。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    源代码中。

    /*********
    *@fn uartLog_flush
    *
    *@简单的日志缓冲区刷新函数
    *
    在该实现中、它旨在由
    *调用 在没有其他内容正在运行时空闲任务。
    *
    * 这是通过在 TI-RTOS
    *中设置空闲任务来实现的 配置脚本、如下所示
    :*
    * VAR 空闲= xdc.useModule('ti.sysbios.knl.Idle');
    * idle.addFunc ('&uartLog_flush');
    *
    注意:必须在包含电源驱动程序之前按顺序添加*
    以在进入睡眠模式之前输出待处理的日志消息。
    *
    * 使用实用程序函数将日志记录转换为用户友好
    * 字符串、然后将其打印到 UART。
    *
    *@param 无。 依赖于全局状态。
    *
    *@返回无。
    *
    *@POST::uartLog_tail 递增至 uartLog_head 所在的位置,然后返回
    */
    void uartLog_flush()
    {
    #if (defined (XDC_runtime_Log_disable_all)&&(XDC_runtime_Log_disable_all=0 )|!copy defined (XDC_runtime_Log_disable_all_locature_event_le_all =0)
    
    
    。*本地记录的未签名。 以使原子段保持较短。 //
    uartLog_EventRec curRec;
    
    //如果我们没有 UART,请勿打扰。 //
    if (NULL == hUart)
    return;
    
    /*在空闲函数(此函数)中发送所有消息。 将被抢占。 //
    while (!uartLog_evBufIsEmpty)
    {
    /*操作缓冲器时的原子部分。 *
    KEY = Hwi_disable();
    
    /*提取最早的数据并移动尾数据*/
    curRec = uartLog_evBuf[uartLog_tail];
    uartLog_tail =(uartLog_tail + 1)% UARTLOG_NUM_EVT_BUF;
    IF (uartLog_tail = uartLog_head)
    uartLog_evBufIsEmpty = true;
    
    /*让其他人玩。 *
    Hwi_restore (key);
    
    /*准备记录中的日志字符串,并打印到 UART。 *
    uartLog_doPrint (&curRec);
    }
    #endif
    } 

    谢谢、

    Kevin。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Kevin、
    我正在尝试查看事件打印的确切位置、或者当您调用其中一个用于打印事件的日志函数时。 因此、我还需要查看 uartLog_doPrint、如果该函数将要打印的事件转发到另一个函数、请也显示该其他函数。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    源代码中。

    /*********
    *内部功能
    */
    *********
    *@fn uartLog_doPrint
    *
    *@brief 会将日志记录转换为字符串。
    *
    * 这是 ti.xdc.runtime.Log's doPrint 方法的副本、但
    * 它不调用 System_printf、而是写入静态缓冲
    器* 然后将其作为原子单元发送到 UART 驱动程序。
    *
    *@param er -要解析和输出的 Log_EventRecord。
    *
    *@返回无。
    //
    #if (定义(xdc_runtime_Log_disable_all)&&(xdc_runtime_Log_disable_all = 0)||!defined (xdc_runtime_Log_disable_all)
    static void uartLog_doPrint (uartLog_EventRec *)
    {
    text_Rope绳索 Id;
    char *fmt;
    //uint32_t hi、lo;
    char *bufPtr = uartLog_outBuf;
    char *bufEndPtr = uartLog_outBuf + UARTLOG_OUTBUF_LEN - 2;//小于2对于\r\n
    
    /*打印序列号(如果有);0不是有效的序列号*/
    if (er->serial_cust){
    system_snprintf (bufPtr、(bufEndPtr - bufPtr)、"#%06u "、er->serial_cust);
    bufPtr = uartLog_outBuf + strlen (uartLog_outBuf);
    }
    
    //打印时间戳(如果有);~0不是有效的时间戳值*//
    * Log_EvtRec 时间戳的格式。 但 LoggerCallback 不提供。
    hi = er->tstamp.hi;
    lo = er->tstamp.lo;
    if (lo!=~0 & hi!=~0){
    system_snprintf (bufPtr、(bufEndPtr - bufPtr)、"[t=0x");
    bufPtr = uartLog_outBuf + strlen (uartLog_outBuf);
    如果(高){
    system_snprintf (bufPtr、(bufEndPtr - bufPtr)、HI、hi);
    bufPtr = uartLog_outBuf + strlen (uartLog_outBuf);
    }
    system_snprintf (bufPtr、(bufEndPtr - bufPtr)、LO、lo);
    bufPtr = uartLog_outBuf + strlen (uartLog_outBuf);
    }
    */
    
    uint16_t seconds = er->tstamp_cust>16;
    uint16_t ifl= er->tstamp_cust & 0xFFFF;
    int fraction =(int)(double)
    
    (buffet/65butr)*
    
    
    、outbudt = 1000、nflu/f)、outbud/f (s)、outbutr =/f)。 在该实现中忽略了这一点。
    text_putMod((text_RopeId) Types_getModuleId(er->evt)、&bufPtr、-1);
    System_snprintf (bufPtr、(bufEndPtr - bufPtr)、 ":");
    bufPtr = uartLog_outBuf + strlen (uartLog_outBuf);
    */
    
    /*输出所有内容、直到现在、并在缓冲区中重新开始。 //
    uart_write (hUart、uartLog_outBuf、(bufPtr - uartLog_outBuf);
    bufPtr = uartLog_outBuf;
    
    //打印事件*/*
    t丝绳= types_getEventId (er->evt);*/*事件 ID 是消息绳*/
    *因为我们不需要
    绳
    /* Log_print()事件*/
    system_snprintf (bufPtr、(bufEndPtr - bufPtr)、(String) iargToPtr (er->arg[0])、
    er->arg[1]、er->arg[2]、er->arg[3]、er->arg[4]、
    er->arg[5]、er->arg[6]、0、0);
    bufPtr = uartLog_outBuf + strlen (uartLog_outBuf);
    }
    否则{
    /* Log_write()事件*/
    FMT = text_ropeText (绳索);
    
    if (text_isLoaded){
    system_snprintf (bufPtr、(bufEndPtr - bufPtr)、fmt、er->arg[0]、er->arg[1]、
    er->arg[2]、er->arg[3]、er->arg[4]、er->arg[5]、
    er->arg[6]、er->arg[7]);
    bufPtr = uartLog_outBuf + strlen (uartLog_outBuf);
    }
    否则{
    system_snprintf (bufPtr、(bufEndPtr - bufPtr)、
    "{evt:FMT=%p、args=[0x%x、0x%x ...]"、
    FMT、er->arg[0]、er->arg[1]);
    bufPtr = uartLog_outBuf + strlen (uartLog_outBuf);
    }
    }
    
    * bufPtr++='\r\n';
    * bufPtr++='\n';
    
    
    UART_WRITE (hUart、uartLog_outBuf、(bufPtr - uartLog_outBuf));
    } 

    谢谢、

    Kevin。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您能否验证 processKeyRight 中的数组"A"是否未保留在堆栈上? 使用调试器或仅打印地址。 如果它不在堆栈上、请尝试在调用 uartLog_outputFxn 中的 memcpy 后打印地址。 打印地址时使用 uartLog_evBuf[uartLog_head].arg[3]。 最后,在 uartLog_doPrint 中的第80行之前,在将 er->arg[3]传递给 System_snprintf 之前执行同样的操作。
    这三个位都应显示相同的地址、并且地址不应位于堆上的某个位置。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    你好 Sasha
    地址都是欺骗的、但问题相同。
    我花了很多时间用于 Log_info %s %f
    我放弃了使用 Log_info 打印%s 和%f
    谢谢。
    Kevin。