[CHANGE] bcm2835_delayMicroseconds(uint32_t micros)

409 views
Skip to first unread message

Arjan

unread,
Feb 14, 2013, 9:44:57 AM2/14/13
to bcm...@googlegroups.com
Hi Mike,

I've changed the function as follows :

// microseconds
void inline bcm2835_delayMicroseconds(uint32_t micros)
{
    struct timespec t1;
    uint32_t start;
   
    // Calling nanosleep() takes at least 100-200 us, so use it for
    // long waits and use a busy wait on the System Timer for the rest.
    start =  bcm2835_st_read();
   
    if (micros > 450)
    {
    t1.tv_sec = 0;
    t1.tv_nsec = 1000 * (long)(micros - 200);
    nanosleep(&t1, NULL);
    }   
 
    bcm2835_st_delay(start, micros);
}

where is

uint32_t bcm2835_st_read(void)
{
    uint32_t st;
    volatile uint32_t* paddr = bcm2835_st + BCM2835_ST_CLO/4;
    st = bcm2835_peri_read(paddr);
    return st;
}

void bcm2835_st_delay(uint32_t start, uint32_t delay_usecs)
{
    volatile uint32_t* paddr = bcm2835_st + BCM2835_ST_CLO/4;
    uint32_t compare = start + delay_usecs;
    while(bcm2835_peri_read(paddr) < compare)
        ;
}

and

/// Base Physical Address of the System Timer registers
#define BCM2835_ST_BASE                    (BCM2835_PERI_BASE + 0x3000)

// Defines for ST
// GPIO register offsets from BCM2835_ST_BASE.
// Offsets into the ST Peripheral block in bytes per 12.1 System Timer Registers
#define BCM2835_ST_CS                             0x0000 ///< System Timer Control/Status
#define BCM2835_ST_CLO                             0x0004 ///< System Timer Counter Lower 32 bits
#define BCM2835_ST_CHI                             0x0008 ///< System Timer Counter Higher 32 bits

I will include the above in the I2C patch. Maybe you want to include it in the mainline as well.

Thanks. Arjan


Mike McCauley

unread,
Feb 14, 2013, 3:22:12 PM2/14/13
to bcm...@googlegroups.com
Hi,

Why did you feel the need to make these changes?

Cheers.
--
Mike McCauley mi...@open.com.au
Open System Consultants Pty. Ltd
9 Bulbul Place Currumbin Waters QLD 4223 Australia http://www.open.com.au
Phone +61 7 5598-7474 Fax +61 7 5598-7070

Radiator: the most portable, flexible and configurable RADIUS server
anywhere. SQL, proxy, DBM, files, LDAP, NIS+, password, NT, Emerald,
Platypus, Freeside, TACACS+, PAM, external, Active Directory, EAP, TLS,
TTLS, PEAP, TNC, WiMAX, RSA, Vasco, Yubikey, MOTP, HOTP, TOTP,
DIAMETER etc. Full source on Unix, Windows, MacOSX, Solaris, VMS, NetWare etc.

Arjan

unread,
Feb 14, 2013, 5:25:31 PM2/14/13
to bcm...@googlegroups.com
Hi,

I did some accuracy/precision measuremen.

Output from attached application :
pi@raspberrypi /opt/data/development/workspace/time/Release $ sudo ./time 500
Init bcm2835 library

0's = 155[501], 30.94

0's = 492[501], 98.20

0's = 495[501], 98.80

0's = 490[501], 97.80

The above shows for the 501 delay's, that 155 calls gives an accurate delay for the current function.
The second is for the changed function.
The third is only using the System Timer.
The fourth is the third C function written in assembler.

Thanks. Arjan


Op donderdag 14 februari 2013 21:22:12 UTC+1 schreef mikem het volgende:
time.zip

Mike McCauley

unread,
Feb 14, 2013, 5:42:17 PM2/14/13
to bcm...@googlegroups.com
Hello,

Thanks.
I rather think that trying to get extreme accuracy in a userland program is
pretty well a waste of time. There is no guarantee that the resulting delay
will be anywhere near what you ask for: it may be *much* more if your user
program gets paged or context swapped.

Cheers.

Arjan

unread,
Feb 14, 2013, 5:51:05 PM2/14/13
to bcm...@googlegroups.com
I agree. Extreme accuracy in a userland program is pretty well a waste of time.

You can prevent swapping by the following :

        struct sched_param sp;
        memset(&sp, 0, sizeof(sp));
        sp.sched_priority = sched_get_priority_max(SCHED_FIFO);
        sched_setscheduler(0, SCHED_FIFO, &sp);
        mlockall(MCL_CURRENT | MCL_FUTURE);


Still no no guarantee that the resulting delay will be anywhere near what you ask for.

However, we can improve the current function (a lot:).

Thanks. Arjan

Op donderdag 14 februari 2013 23:42:17 UTC+1 schreef mikem het volgende:

Sum

unread,
Apr 1, 2013, 4:42:32 AM4/1/13
to bcm...@googlegroups.com
Hello Arjan,

Can you please let me know where we need to place this code in the driver. Can you please share more details of this. 

Thanks & Regards
Suman

Arjan

unread,
Apr 15, 2013, 9:16:09 AM4/15/13
to bcm...@googlegroups.com
Suman,

The code at the beginning of main would be like this :

printf("Init realtime environment\n");

if (geteuid() == 0) {
struct sched_param sp;
memset(&sp, 0, sizeof(sp));
sp.sched_priority = sched_get_priority_max(SCHED_FIFO);
sched_setscheduler(0, SCHED_FIFO, &sp);
mlockall(MCL_CURRENT | MCL_FUTURE);
fprintf(stderr, "Running with realtime priority!\n");
} else {
fprintf(stderr, "Not running with realtime priority.\n");
}

Thanks, Arjan

Op maandag 1 april 2013 10:42:32 UTC+2 schreef Sum het volgende:
Reply all
Reply to author
Forward
0 new messages