Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
14 years ago

usleep() issue

Hello.

In this code:

fprintf(lcd_name, string1);
usleep(2000000);
fprintf(lcd_name, string2);
second string should appear on LCD after 2 sec. But it appears without any delays!

It's interesting that this code

printf("a");
usleep(2000000);
printf("b");
runs right - second string appears in Nios console after 2 sec.

What's the matter?

9 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    In the first case, you say that the second string appears with no delay. Is there a chance that both strings show up 2 seconds after the routine runs?

    My theory is that the usleep is preventing the fprintf code from running. After the usleep expires, both strings are sent to the display. There is an easy way to check this.

    
    printf ("start\n");
    usleep(5000000);
    fprintf(lcd_name, string1);
    usleep(2000000);
    fprintf(lcd_name, string2);
    

    With this, you should see the "start" on the console then 7 seconds later (not 5) you should see both strings on the LCD.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Your theory is right.

    How to fix it? I need delay before second string. Should I use another delay function?

    addition:

    I also try to use the empty loop

    for (i=1 ; i<100000000 ; i++) {};

    but it doesn't work too.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    usleep is likely to be implemented as a blocking loop not far different from the for loop.

    On the other hand a true sleep function is supposed to suspend the calling task and release the control to other tasks which possibily run at lower priorities.

    I guess the lcd management driver runs in a lower priority task (or rather in a lower priority isr, if you don't use any OS): then you send the data with fprintf but the driver is not assigned any cpu time until your function has completed.

    The solution depends on your application structure.

    If you are using an OS, you should have another sleep "true" function available.

    Also debug into usleep in order to find out how it has been implemented; maybe you can set some project options in order to make it work the proper way.

    If the fprintf and sleep calls are in a isr, make sure it's not a high priority one.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I don't use OS on the Nios.

    I wrote my own LCD vhdl driver so I rule LCD using UART (altera_avalon_uart). 'fprintf' transfers string with usual serial protocol.

    I'll try to debug, thanks.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Then you must focus on the altera_avalon_uart driver. For sure your fprintf sends the string immediately to the uart HAL driver but data is kept in the transmit buffer until the usleep completes, since this blocking functions prevents the HAL driver from sending data to the actual serial port hardware, as I described above.

    What's your avalon_uart implementation? small or fast?

    If it's the small one, you should have a uart poll call somewhere in a loop: you must place periodic calls to this in the sleep function, too.

    If it's the fast implementation, you probably need to fix irq priorities.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Or use a UART with a large enough hardware tx fifo to cover normal lines of debug output and then either discard or spin inside the 'transmit character' function.

    Whatever you do, at some point the decision has to be made whether to

    spin/sleep/discard when the tx buffer is full, having a single hardware fifo and very simple software might actually use the least resource!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi

    my suggestion would be not to use usleep. Instead use the system_clk. For example:

    alt_u32 wait_time = alt_nticks() + xxx;
    while(wait_time > alt_nticks());
    Does that make sense?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Hi

    my suggestion would be not to use usleep. Instead use the system_clk. For example:

    alt_u32 wait_time = alt_nticks() + xxx;
    while(wait_time > alt_nticks());
    Does that make sense?

    --- Quote End ---

    This wil possibly improve the precision of time delay but it will not solve Hatter's problem: it's still a blocking loop.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Maybe the output buffer of fprintf is not flushed until after the second call. Could maybe try to fflush(lcd_name); after the first fprintf.