AnsweredAssumed Answered

Nanosecond delay

Question asked by ferner.joe on Mar 18, 2018
Latest reply on Mar 19, 2018 by dhenry

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;
  }
}

Outcomes