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.

Make scanf blocking

Other Parts Discussed in Thread: TM4C1294NCPDT

Hello,

Following one of your examples for a TM4C device, I've made a UART a console so that calls to stdio functions go through that port.  I'm using scanf to read input from that UART within a task and I'd really like scanf to behave as a blocking call.  By default, it does not appear to do so.  Is there a way I can make this a blocking function?  I'm using TI-RTOS 2.16.x within CCS 6.2 on a TM4C1294NCPDT.


Thanks,
Eric

  • Hi Eric,

    I looked at the UART console example and the UART is configured to be in blocking mode. So, I would expect the scanf() to block. How is the UART in your application configured? Is it similar to the UARTconsole example? Can you share your project? Does the scanf() in UARTconsole behave same on your board?

    Vikram
  • Hi Vikram,

    Yeah, I was expected scanf() to block as well.  But, it wasn't working that way.  I wish I could send you my project, but my local working copy got corrupted so all I can send are the source files.  In the event this is helpful, please find them attached. (I can send the project on Monday from my original working copy).  In "Consoletask.c" is the task "consoleFxn" which is causing me the problem.  I'm reading a string using scanf() and processing this string in a subroutine. 

    Let's follow the case when the input string is simply "b".  You'll see that this causes a Semaphore_post() in my code.  The problem is that the task enabled by the post doesn't execute.  But, if I put a Task_sleep(1) immediately following the Semaphore_post(), the secondary task will run.  The problem is definitely with the scanf() function because when I use a blocking "UART_read()" for the same purpose, the secondary task executes properly.  Even though scanf() is linked to a blocking UART call, I was wondering if there was some upper level loop that was preventing the blocking from actually happening.


    Thanks for your help!

    Eric

    4405.EAK SCANF.zip

  • Hi Eric,

    Both your tasks are of same priority, so when you post the semaphore it may not switch to the other task. Also, can you look at the ROV tool (in debugger view, Tools > ROV) and check the Task status in Task > Detailed view. This would show what states the Tasks are after reading the input from UART. My guess is both are blocked. I would recommend increasing the priority on BMP280Fxn Task.

    Regarding the difference between scanf() and UART_read(), I still have to dig in deeper into the code. The scanf() is part of the C runtime provided by the TI compilers and probably you may get faster response for questions on scanf() in the compiler forum. As far as I know, the scanf() should call the UART_read() and both should behave the same way in your Task.

    Vikram
  • I would also recommend using breakpoints to debug. You can place a breakpoint in your BMP280Fxn after Semaphore_pend() to check if it's reaching there.
  • Hi Vikram,

    I did try raising the priority of the other task, but that did not change things.  Using breakpoints, I confirmed that I only get to the second task once every other command input.  To continue with my previous scenario - the first time a "b" is entered, the second task does not execute.  However, the second "b" (or any other command input) will allow the second task to run.  I only see this problem using scanf().  Reading the command through UART_read() works just fine. 

    Thanks for your help,

    Eric

  • Can you set the Semaphore supportsPrority config to true in your .cfg?

    Semaphore.supportsPriority = true;

    Vikram
  • And I would highly recommend using ROV for this issue. It would clearly show you which state the Tasks are in. Use breakpoints to halt program at certain statements in your program and look at ROV Task and Semaphore module views.

    One other small change that I recommend, if you are using readBarometer Semaphore for mutex purposes only use binary semaphore mode instead of counting semaphore.

    Vikram
  • Hi Vikram,

    Thank you for your suggestions.  I added the line for semaphore priority to my config file.  Unfortunately, this didn't seem to make a difference. 

    I'm puzzled by what I'm seeing with the ROV tool versus the execution of the program.  I set a breakpoint on xferBMP280() within the task "BM280Fxn".  The first time I reach this break point, things make sense:  (1) userconsole task is ready, (2) readBarom task is running (task that is unblocked by enteering a 'b" through the console), and (3)  idle is ready.  But, when I restart the execution, the remaining part of readBarom does not complete.  Instead, execution seems to be given to the idle task.  At least, this is what the ROV tool is telling me.  At this point, the ROV indicates all tasks are blocked, but idle is running. 

    When I enter a second "b" and re-encounter the breakpoint, the readBarom tasks completes it's execution from the previous call.  Like the first encounter, userconsole is ready, readBarom is running and idle is ready.  It's really just not clear to me how BIOS ends up in the idle task before completing the execution of a higher priority task.  FYI - readBarom is at priority 2 and userconsole is priority 1.

    Based on what I'm seeing in the ROV, scanf() does seem to be a blocking call.


    Eric

  • Hi Eric,

    The BM280Fxn task blocks probably because of the printf()'s in xferBMP280(). I know this from my tests though I did not spend time on finding why it blocks. Instead, I used System_printf() which worked fine for me.

    BIOS will end up in idle task when all other tasks are blocked. Since both your tasks got blocked, idle Task kicked in.

    PS: You can use GateMutex instead of the Semaphore for mutex operations in xferBMP280()

    Vikram
  • Hi Vikram,

    Thanks again!  I think this has fixed it.  Using System_printf() instead of the regular printf() seems to have done the trick.  I was using the regular printf() because I needed to monitor floating pointing values.  I just discovered how to extend System_printf() to include float, so I'll change my code to use that function. 


    Thanks again for your help!  I'll mark your last post as the answer.

    Eric

    PS - I've not used the GateMutex before.  What would be the advantage over a Semaphore?

  • Glad that it works!

    Eric Kaltenbacher said:
    PS - I've not used the GateMutex before.  What would be the advantage over a Semaphore?

    I am not sure if it has an advantage over Semaphore. I suggested GateMutex as it is meant to be used for gating operations (like in your xferBMP280()) and also provides a better readability of the code.

    VIkram