Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem


Set delay time between two functions

Posted by yeerang on December 11, 2014


I want to call the function i2cmastertransaction() in the task, and there are i2csend() and i2creceive() in the i2cmastertransaction() function. Those i2csend() and i2creceive() functions operates with Queue.

I would like to set some delay time between i2csend() and i2creceive(), but it seems that delay_us() and vTaskDelay were not effective.

Could you advise how to set the delay time in the task? Thank you in advance.

Set delay time between two functions

Posted by heinbali01 on December 11, 2014

Hi Yeerang,

Functions like delay_us() are implemented as counted loops, using the CPU intensively.

vTaskDelay() has a lower resolution (of 1 clock tick) but it does make the task sleep.

Your i2C_receive() already blocks while waiting for data in xQueueReceive(), why would you want to have an extra delay?


Set delay time between two functions

Posted by yeerang on December 11, 2014

Because if i2c_receive() request the response too fast, there will be the value which means 'the response is not ready'. Could I set the delay time using the vTaskDelay()?

Set delay time between two functions

Posted by heinbali01 on December 11, 2014

You can always use:

~~~~~ void vTaskDelay( const TickType_t xTicksToDelay ) ~~~~~

to introduce some delay.

Your i2c_receive() calls xQueueReceive() and if it is called too quickly, you say there is a value which means 'the response is not ready'.

Shouldn't it just wait once more until the real response comes in?

Set delay time between two functions

Posted by yeerang on December 12, 2014

I don't get what you mentioned in the last line.

I alreaday tried to use vTaskDelay as below: >i2cmastertransaction(){ i2csend(); vTaskDelay(); i2creceive(); }

And it was not working as what I wanted.

Set delay time between two functions

Posted by rtel on December 12, 2014

It is a bit of a crude device in this case. Ideally you would want to be using DMA or at least interrupt and let the hardware do it for you (assuming you are using an I2C peripheral, and not just bit-banging the protocol through an IO port. If not then the next best is to make no assumptions about timing, but instead query the hardware to see the system state (i.e. read the registers).


Set delay time between two functions

Posted by heinbali01 on December 12, 2014

In my experience, writing a perfect interrupt-driven TWI (I2C) device driver is very complex. Using DMA will make it more efficient but also more complex. Within each interrupt you'll have to ask your self: where am I in the process? what has been done? What must be done now?

Also, very important is error handling. It is possible that some TWI device gets into a state where the bus becomes totally unusable. In that case there are two ways to solve it: either a total power reset, or a bus-reset.

In case you'll encounter a blocked bus in which SDA is constantly low, here's a way to do a bus-reset:


void setdatadir( int direction ); void setdataval( int value );

int get_data( void ); /* read the SDA pin */

void setclockdir( int direction ); void setclockval( int value );

void us_delay( int useconds );

void twigpioreset (int aDoLock) { int bitNr; /* * In case a part is keeping SDA constantly low by * pulling it down, a bus reset is needed: * 1. Clock up to 9 cycles while SDA in high-impedance * 2. Look for SDA high in each cycle while SCL is high * 3. Create a start condition as SDA is high. */

/* First define SDA/SCL temporarily as normal GPIO's */

set_clock( 1 );
set_data( 1 );
set_clock_dir( _OUTPUT );
set_data_dir( _INPUT );
    // CLOCK  11110011 11001010 10101010 10101010
    unsigned clock_pattern = 0xF3CAAAAA;
    // DATA   11100001 10011111 11111111 11111111
    unsigned data_pattern  = 0xE19FFFFF;
    // READ   00000000 00001111 11111111 11111111
    unsigned read_pattern  = 0x000FFFFF;

    for (bitNr = 0; bitNr < 32; bitNr++) {
        /* Clock out any data a slave might have */
        set_clock_val( clock_pattern & 1 );

        if (read_pattern & 1)
            set_data_dir( _INPUT );
            set_data_dir( _OUTPUT );
            set_data_val( data_pattern & 1 );
        us_delay( 20 ); /* Minimal 20 uS delay */

        if( ( read_pattern & 1 ) &&
            ( clock_pattern & 1 ) &&
            ( get_data( ) != 0 ) )
            /* A device has released the SDA.
             * This should happen between 1 and 9 bits.
        clock_pattern >>= 1;
        data_pattern  >>= 1;
        read_pattern  >>= 1;
/* Give SDA/SCL pins back to the TWI peripheral */

} ~~~~~

How much data do you exchange with your I2C devices and how often?

If you're polling some chip occasionally, like once a second, you could also consider leaving-out the interrupts and DMA and just send, poll, receive.

Regards, Hein

[ Back to the top ]    [ About FreeRTOS ]    [ Privacy ]    [ Sitemap ]    [ ]

Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

NXP tweet showing LPC5500 (ARMv8-M Cortex-M33) running FreeRTOS.

Version 10.1.1 of the FreeRTOS kernel is available for immediate download. MIT licensed.

View a recording of the "OTA Update Security and Reliability" webinar, presented by TI and AWS.


FreeRTOS and other embedded software careers at AWS.

FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Espressif ESP32

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers


STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS

Xilinx Microblaze and Zynq partner