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.

Writing to UART from main() context (or whats the best way to do this)

Other Parts Discussed in Thread: SYSBIOS, EK-TM4C1294XL

The default output for (System_printf) in the examples I have been looking at is the CIO console.  I wanted to also send it to UART0 (where I also have a command prompt).  This is what I HAVE been doing:


  1. In my RTOS config:
    SysMin.outputFxn = "&externOutputFunc";
  2. In code I have a multiple console facility where a session is either a telnet sesison or a UART - too large to paste all here.  But the output function mentioned in the RTOS config looks like this (potentially writing to both):

    #define PDB_ENABLE_CIO_OUTPUT
    extern int HOSTwrite(int, const char *, unsigned);
    int externOutputFunc(const char *buf, unsigned int size)
    {
      int ret = 0;

      if (stg_defOutputSession)
        ret = SessWrite(stg_defOutputSession, buf, size);

    #ifdef PDB_ENABLE_CIO_OUTPUT
      {
        // This chunk taken from generated (default) code when outputFxn is
        // left at "null"
        int printCount;

        while (size != 0) {
          printCount = HOSTwrite(1, buf, size);
          if ((printCount <= 0) || (printCount > size)) {
            break; /* ensure we never get stuck in an infinite loop */
          }
          size -= printCount;
          buf = buf + printCount;
        }
      }
    #endif

      return ret;
    }

  3. The UART in this case was opened as follows:

    UART_Params_init(&uartParams);
    uartParams.writeDataMode = UART_DATA_TEXT;
    uartParams.readDataMode = UART_DATA_BINARY;
    uartParams.readReturnMode = UART_RETURN_FULL;
    uartParams.readEcho = UART_ECHO_OFF;
    uartParams.baudRate = 115200;
    sess->uart = UART_open(uartId, &uartParams);

  4. When the session is a UART  (and in the case in question it is) SessWrite() just executes a
    UART_write(sess->uart, (void*)buffer, size);

The above works quite well, with the only gotcha that System_printf()/flush calls from the main() context are only sent to the CIO console.  I tried to move the setting of stg_defOutputSession into main and the UART_write dies because we are not in a task context (semaphore).


So my questions/options are:

  1. Really?  We don't expect folks to write to UART in main()  that does not seem reasonable.
  2. I don't think I can just delay the flush - because a flush will occur if a buffer is filled and then I have an unpredictable system
  3. I'm pretty sure I don't want to switch to UART in callback mode just for this issue
  4. I'm also pretty sure that while I launch the UART task from main() that it does not actually run till I call BIOS_Start()
  5. Are System_printf() logs intended only for development only (CIO console connected)
  6. Should I just buffer (another layer of buffer) if not in Task context?  Also seems a little heavy

Please let me know if I'm looking it all wrong

Thanks!

  • 1) Why not do this in a Task that runs once? In fact...do your whole UART_open() thing from a Task.
    4) That's correct5) Yes, ideally, its only for development.
    6) I don't understand why you wouldn't just do this in a Task context? Must it be in main()?
    Judah
  • Thanks Judah

    So your recommendation is to have

    void initTask()
    {
      Board_initGeneral();
      Board_initEMAC();
      Board_initGPIO();
      Board_initUART();
      Board_initI2C();
    
      UART_Params_init(&uartParams);
      ...;
      sess->uart = UART_open(uartId, &uartParams);
      ...
    
      // launch other threads from here
    }
    
    
    int main(void)
    {
      TaskCreate(iniTask, "initTask", OS_TASKPRINORM, 0x1000, 0, 0, 0);
      BIOS_start();
    }
    



    on #1 & #6 I considered it but it seemed like it goes against most//all the examples I saw and can't imagine that I'm the only one that scratches his head on this one.

    On # 5 If System_printf() is just for development, what is the recommended way to print to UART (for field service environment)

    Thanks

  • One more thing

    I think that even of I get over my initialization issue I still run the risk of BIOS invoking my method (cauing me to write to UART) while in  Hwi context.  Causing this double crash.

    This leads me to state that the way I'm binding the System_printf output to UART is not the right way to do this...   which brings me back to point #1 in my original question 

  • A couple of things:

    1.  I would keep the Board_initXXX() calls in main().  In SYSBIOS main is basically for init so I would keep those in main().  Do the UART_open in a Task.

    2.  Generally you should not be calling System_printf in your ISR or Hwi context.  It can be done but with some caution.  If you're writing to the UART too with System_printf, you cannot do this because the UART_write call is a blocking call (calls Semaphore_pend).

    3. Your Hwi should be design to be fast and small...something like a Semaphore_post() that unblocks a Task.  The real work should be done in the Task...and this is where you ought to be calling UART_write or System_printf.

    Judah

  • 1. Thats what I suspected - but the logs I would like to capture emanate from those init routines

    2, 3. I agree and understand (and understood these limitations before my original post). Its not MY HWI that decided to print - its a default exception handler 

    So we all know what NOT to do, but what is the blessed method to redirect System_printf() output to a UART (while including all logs you would see on the CIO console)

  • What device are you on?
    On some devices, we support a polling write instead of a blocking write, so you could possibly do this depending on what device you are on.
    When you do the UART write, use UART_writePolling() instead. This function does not block and just spins.
    There's a TI drivers exampled called "UART console" that does something very similar to what you are wanting to do.
    But it is only available on some devices which the UART supports this type of behaviour.
    Judah
  • Hi Judah

    I'm currently using EK-TM4C1294XL, whats a good way to check if supported, just to see if its in my libs or is there a physical restriction that will make it not work on some platform regardless of code?
  • Hi I think its supported on your board.  I believe its limited by the UART hardware.  Some UARTs support this and others dont.

    Could you check to see if the example is available for your board in CCS:

    1.  View ->  Resource Explorer Examples
    2.  Look for your device and expland it.
    3.  Under Driver Examples -> UART Examples -> UART console

     

    Judah