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: how can i use ' Log_info1 %s ' ?

Part Number: CC2650STK
Other Parts Discussed in Thread: CC2650, , SYSBIOS

Tool/software: TI-RTOS

Hello Ti Team

I have 1 question.

I use Log_info1 function but, %s is not uart log print

how can i use log %s?

  • Hi Kevin,

    What logger are you using?

    Thanks,
    Gerardo
  • Hi Gerardo Gomez Martinez ,

    I using to uart_logs and xdc logs

    main board CC2650STK and CC2650_launchpad

    CC2650_lanchpad base source 'Project zero' in uart_logs merge to CC2650_sensortag

    Base IDE : CCS 7.0

    include file
    #include <xdc/runtime/Log.h>

    include app_ble.cfg source


    // Remaining Modules
    var Diags = xdc.useModule('xdc.runtime.Diags');
    var Main = xdc.useModule('xdc.runtime.Main');
    var Reset = xdc.useModule('xdc.runtime.Reset');




    // Need Text loaded for formatting of Log_info/warning/error, but not for Log_print.
    Text.isLoaded = true;

    // Logging
    var Log = xdc.useModule('xdc.runtime.Log');

    // Override error output color with ANSI codes, and use shorter (file.c:line) format.
    Log.L_error = {
    mask: Diags.STATUS,
    level: 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,
    level: Diags.WARNING,
    msg: "\x1b[33;1mWARNING:\x1b[0m (%s:%d) %$S"
    };

    // Pull in LoggerCallback
    var LoggerCallback = xdc.useModule('xdc.runtime.LoggerCallback');

    // Tell LoggerCallback to call our output function
    LoggerCallback.outputFxn = "&uartLog_outputFxn";

    // Tell the Idle module to add our flush() function to the idle loop (before Power)
    var Idle = xdc.useModule('ti.sysbios.knl.Idle'); // Add if Idle isn't already imported.
    Idle.addFunc('&uartLog_flush');

    // Create a static instance of LoggerCallback and set as default Main logger
    var loggerParams = new LoggerCallback.Params();
    loggerParams.arg = 1;

    // Only for Main (code that's not in an rtsc module)
    Main.common$.logger = LoggerCallback.create(loggerParams);
    //Defaults.common$.logger = LoggerCallback.create(loggerParams); // Use for all log events

    // Turn on USER1 logs and INFO in Main module (user code). Turn off USER2 for fun.
    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;

    How can i using 'Log_info1("aaa1=[%s]",a);' ?

    Thanks to read reply,

    Best regards.

    kevin.
  • Kevin,
    can we see your uartLog_outputFxn?
  • here uart_logs.c in function  uartLog_outputFxn




    /********************************************************************* * @fn uartLog_outputFxn * * @brief User supplied LoggerCallback output function. * typedef Void (*LoggerCallback_OutputFxn)(UArg,Log_EventRec*,Int); * * This function is called whenever the LoggerCallback module needs * to output a log event. * * This implementation fills a very basic ring-buffer with log records, * with relatively low overhead, and relies on another function to * convert log records to text and transmit the string out on UART. * * Requires LoggerCallback to be the ILogger provider module. * Initialized via LoggerCallback.outputFxn = "&uartLog_outputFxn"; * in the TI-RTOS configuration script. * * Note that Log must be included as well to use the interface, and * a LoggerCallback instance must be made and assigned as default. * In total, therefore: * * var Log = xdc.useModule('xdc.runtime.Log'); * var LoggerCallback = xdc.useModule('xdc.runtime.LoggerCallback'); * * LoggerCallback.outputFxn = "&uartPrintf_logOutputFxn"; * * var loggerParams = new LoggerCallback.Params(); * Defaults.common$.logger = LoggerCallback.create(loggerParams); * * @param a0 - User supplied argument when creating the LoggerCallback logger. * pRec - Pointer to Log_EventRec created by LoggerCallback * numArgs - Number of arguments used in pRec. * * @return None. * * @post ::uartLog_head is incremented, and if it becomes equal to _tail, * both are moved together, discarding the oldest record. */ void uartLog_outputFxn(UArg a0, Log_EventRec *pRec, int32_t numArgs) { #if (defined(xdc_runtime_Log_DISABLE_ALL) && (xdc_runtime_Log_DISABLE_ALL == 0)) || !defined(xdc_runtime_Log_DISABLE_ALL) unsigned int key; uint8_t moveTail = 0; /* Disable interrupts while adding record */ key = Hwi_disable(); /* Copy into current head */ //uartLog_evBuf[uartLog_head].tstamp = pRec->tstamp; /* If real Log_EvtRec */ uartLog_evBuf[uartLog_head].tstamp_cust = AONRTCCurrentCompareValueGet(); uartLog_evBuf[uartLog_head].serial_cust = uartLog_evtNum; uartLog_evtNum++; //uartLog_evBuf[uartLog_head].serial = pRec->serial; /* If LogEvtRec */ uartLog_evBuf[uartLog_head].evt_cust = pRec->evt >> 16; /* Ignore ModuleID */ memcpy(uartLog_evBuf[uartLog_head].arg, pRec->arg, sizeof(__TA_xdc_runtime_Log_EventRec__arg)); /* Copy log arguments */ /* Discard oldest if buffer is full */ if ( !uartLog_evBufIsEmpty && (uartLog_head == uartLog_tail) ) { moveTail = 1; } /* Increment head with wrap */ uartLog_head += 1; if (uartLog_head == UARTLOG_NUM_EVT_BUF) { uartLog_head = 0; } if (moveTail) { uartLog_tail = uartLog_head; } /* This is used to discern whether head==tail means empty or full*/ uartLog_evBufIsEmpty = false; /* Let mayhem commence */ Hwi_restore(key); #endif };

  • I forgot to ask about uartLof_flush. That's the one where events are interpreted and displayed.

  • in source code.

    /*********************************************************************
     * @fn      uartLog_flush
     *
     * @brief   Log-buffer flush function
     *
     *          In this implementation it is intended to be called by the
     *          Idle task when nothing else is running.
     *
     *          This is achieved by setting up the Idle task in the TI-RTOS
     *          configuration script like so:
     *
     *          var Idle = xdc.useModule('ti.sysbios.knl.Idle');
     *          Idle.addFunc('&uartLog_flush');
     *
     *    NOTE: This must be added _before_ the Power driver is included, in order
     *          to output the pending log messages before going to sleep.
     *
     *          Uses a utility function to convert a log record to a user-friendlier
     *          string which is then printed to UART.
     *
     * @param   None. Relies on global state.
     *
     * @return  None.
     *
     * @post    ::uartLog_tail is incremented to where uartLog_head is, then returns
     */
    void uartLog_flush()
    {
    #if (defined(xdc_runtime_Log_DISABLE_ALL) && (xdc_runtime_Log_DISABLE_ALL == 0)) || !defined(xdc_runtime_Log_DISABLE_ALL)
      unsigned int key;
    
      /* Local copy of current event record. To keep atomic section short. */
      uartLog_EventRec curRec;
    
      /* If we don't have UART, don't bother. */
      if (NULL == hUart)
        return;
    
      /* In the Idle function (this) send all messages. Will be preempted. */
      while(!uartLog_evBufIsEmpty)
      {
        /* Atomic section while manipulating the buffer. */
        key = Hwi_disable();
    
        /* Extract oldest and move tail */
        curRec = uartLog_evBuf[uartLog_tail];
        uartLog_tail = (uartLog_tail + 1) % UARTLOG_NUM_EVT_BUF;
        if (uartLog_tail == uartLog_head)
          uartLog_evBufIsEmpty = true;
    
        /* Let the others play. */
        Hwi_restore(key);
    
        /* Prepare log string from record, and print to UART. */
        uartLog_doPrint(&curRec);
      }
    #endif
    }

    Thanks,

    kevin.

  • Kevin,
    I am trying to see the exact place where printing of the events occurs, or when you call one of the Log functions that print the events. So, I also need to see uartLog_doPrint, and if that function forwards an event to be printed to yet another functions, please show that other function too.
  • here in source code.

    /*********************************************************************
     * INTERNAL FUNCTIONS
     */
    /*********************************************************************
     * @fn      uartLog_doPrint
     *
     * @brief   Converts log records to strings.
     *
     *          This is a copy of ti.xdc.runtime.Log's doPrint method, but
     *          instead of calling System_printf, it writes into a static buffer
     *          which is then sent to the UART driver as an atomic unit.
     *
     * @param   er - Log_EventRecord to be parsed and output.
     *
     * @return  None.
     */
    #if (defined(xdc_runtime_Log_DISABLE_ALL) && (xdc_runtime_Log_DISABLE_ALL == 0)) || !defined(xdc_runtime_Log_DISABLE_ALL)
    static void uartLog_doPrint(uartLog_EventRec *er)
    {
      Text_RopeId rope;
      char       *fmt;
      //uint32_t    hi, lo;
      char       *bufPtr = uartLog_outBuf;
      char       *bufEndPtr = uartLog_outBuf + UARTLOG_OUTBUF_LEN - 2; // Less 2 for \r\n
    
      /* print serial number if there is one; 0 isn't a valid serial number */
      if (er->serial_cust) {
        System_snprintf(bufPtr, (bufEndPtr - bufPtr), "#%06u ", er->serial_cust);
        bufPtr = uartLog_outBuf + strlen(uartLog_outBuf);
      }
    
      /* print timestamp if there is one; ~0 isn't a valid timestamp value */
      /* Formatting of Log_EvtRec timestamps. But LoggerCallback doesn't provide.
      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);
        if (hi) {
          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 ifraction = er->tstamp_cust & 0xFFFF;
      int fraction = (int)((double)ifraction/65536 * 1000);  // Get 3 decimals
    
      System_snprintf(bufPtr, (bufEndPtr - bufPtr), "[ %d.%03u ] ", seconds, fraction);
      bufPtr = uartLog_outBuf + strlen(uartLog_outBuf);
    
      /* print module name. This is ignored in this implementation.
      Text_putMod((Text_RopeId)Types_getModuleId(er->evt), &bufPtr, -1);
      System_snprintf(bufPtr, (bufEndPtr - bufPtr), ": ");
      bufPtr = uartLog_outBuf + strlen(uartLog_outBuf);
      */
    
      /* Ouput everything till now and start over in the buffer. */
      UART_write(hUart, uartLog_outBuf, (bufPtr - uartLog_outBuf));
      bufPtr = uartLog_outBuf;
    
      /* print event */
      /* rope = Types_getEventId(er->evt); */  /* the event id is the message rope */
      rope = er->evt_cust; /* Don't need getEventId as we already have it */
      if (rope == 0) {
        /* Log_print() event */
        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);
      }
      else {
        /* Log_write() event */
        fmt = Text_ropeText(rope);
    
        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);
        }
        else {
          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';
      *bufPtr++ = '\n';
    
    
      UART_write(hUart, uartLog_outBuf, (bufPtr - uartLog_outBuf));
    }

    Thanks,

    kevin.

  • Can you verify that the array 'a' in processKeyRight is not kept on stack? Use the debugger or just print the address. If it's not on stack, try printing the address just after the call to memcpy in uartLog_outputFxn. Use uartLog_evBuf[uartLog_head].arg[3] when printing the address. Finally, do the same just before line 80 in uartLog_doPrint, before you pass er->arg[3] to System_snprintf.
    All three should display the same address, and the address should not be somewhere on heap.
  • hello sasha
    address is all cheked but same problem.
    I spent a lot of time for Log_info %s %f
    I gave up using Log_info print %s and %f
    Thanks.
    kevin.