Skip to main content
joe23
Associate II
March 18, 2018
Question

Nanosecond delay

  • March 18, 2018
  • 9 replies
  • 2337 views
Posted on March 18, 2018 at 15:32

EDIT: Not sure where my intro paragraph went on the first time I posted.

I have the below code working with inline assembly nops. Now I want to have the code be clock independent. The below code is my attempt at doing this. The problem is the loops end up being 5-10 loops, which doesn't give me the needed resolution to get accurate 850ns, 800ns, 450ns , 400ns delays. Is there a better way to get nanosecond delays?

#define LOOPS_FOR_NS(ns) (ns * 800U / (SystemCoreClock / 1000))
uint32_t loops400ns = LOOPS_FOR_NS(400U);
uint32_t loops450ns = LOOPS_FOR_NS(450U);
uint32_t loops800ns = LOOPS_FOR_NS(800U);
uint32_t loops850ns = LOOPS_FOR_NS(850U);
volatile uint32_t loops;
for (;;) {
 if (p & bitMask) { // ONE
 // High 800ns
 port->BSRR = setPin;
 loops = loops800ns;
 asm(
 'mydelay_800:'
 'subs %[loops], 1;'
 'bne mydelay_800;'
 : // no output
 : [loops] 'r'(loops)
 );
 // Low 450ns
 port->BSRR = resetPin;
 loops = loops450ns;
 asm(
 'mydelay_450:'
 'subs %[loops], 1;'
 'bne mydelay_450;'
 : // no output
 : [loops] 'r'(loops)
 );
 } else { // ZERO
 // High 400ns
 port->BSRR = setPin;
 loops = loops400ns;
 asm(
 'mydelay_400:'
 'subs %[loops], 1;'
 'bne mydelay_400;'
 : // no output
 : [loops] 'r'(loops)
 );
 // Low 850ns
 port->BSRR = resetPin;
 loops = loops850ns;
 asm(
 'mydelay_850:'
 'subs %[loops], 1;'
 'bne mydelay_850;'
 : // no output
 : [loops] 'r'(loops)
 );
 }
 if (bitMask >>= 1) {
 // Move on to the next pixel
 asm('nop;');
 } else {
 if (ptr >= end) {
 break;
 }
 p = *ptr++;
 bitMask = 0x80;
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

    This topic has been closed for replies.

    9 replies

    henry.dick
    Associate II
    March 19, 2018
    Posted on March 19, 2018 at 11:14

    absolutely correct.

    Tesla DeLorean
    Guru
    March 19, 2018
    Posted on March 19, 2018 at 13:54

    DWT_CYCCNT works well at benchmarking.

    Better to use a TIM for hard signal placement, either modulating the PWM, or driving GPIO+DMA

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Uwe Bonnes
    Chief
    March 19, 2018
    Posted on March 19, 2018 at 15:30

    These delay will jitter if interrupts happen. Why not look at some fast running counter and wait until that counter reaches some value you precalculate?

    henry.dick
    Associate II
    March 19, 2018
    Posted on March 19, 2018 at 15:55

    Software delays aren't that useful for precision timing, as they are dependent on too many factors.

    Nano seconds delays using software are even worse.

    If you absolutely have to have extremely short delays, think of hardware based solutions instead. 

    joe23
    joe23Author
    Associate II
    March 19, 2018
    Posted on March 19, 2018 at 15:57

    Thanks, I think I'm going to look at DMA based Timers and see if I can get that to work.

    Tesla DeLorean
    Guru
    March 19, 2018
    Posted on March 19, 2018 at 16:00

    Are you signalling an LED controller?

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    joe23
    joe23Author
    Associate II
    March 19, 2018
    Posted on March 19, 2018 at 16:13

    Yes, trying to drive Adafruit NeoPixel (

    https://www.adafruit.com/product/1138

    ) 2m strip of RGB LEDs