2018-03-18 07:32 AM
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;
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2018-03-19 03:14 AM
absolutely correct.
2018-03-19 05:54 AM
DWT_CYCCNT works well at benchmarking.
Better to use a TIM for hard signal placement, either modulating the PWM, or driving GPIO+DMA
2018-03-19 07:30 AM
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?
2018-03-19 07:55 AM
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.
2018-03-19 07:57 AM
Thanks, I think I'm going to look at DMA based Timers and see if I can get that to work.
2018-03-19 09:00 AM
Are you signalling an LED controller?
2018-03-19 09:13 AM
Yes, trying to drive Adafruit NeoPixel (
) 2m strip of RGB LEDs2018-03-19 09:38 AM
There have been other threads related to WS2812B type devices, basically modulating PWM from a large pattern buffer, ie Update loads new CCRx
Driving multiple devices via a common GPIO bank with TIM triggered DMA to GPIOx->ODR or GPIOx->BSRR.
On F4 would need to use DMA2
2018-03-19 09:48 AM
People have been driving those things with 8 bit mcus so you can certainly do it with a faster and more capable chip. Lots of possibilities.