My goal is to create a single pulse with the RPI pico by clearing and setting a hardware pin in software. I am attempting to do this in software because I did not see a way to provide a single non-repetitive pulse through one of the timer channels.
The resolution of the pulse width can be as much as 32ns, which should be easy to achieve with a 125MHz clock. Any pulse longer than 1us on the hardware pin will physically destroy the circuit.
In the simplest form the code should initialize a pin to the high state, pull the pin low, wait, and then set the pin high. There should be a way to predictably adjust the time between the low and high states.
In the code below, I would expect that every NOP between the gpio_clr and gpio_set commands increased the pulse width by either 8ns or 16ns. However, there is no consistency to the relation between pulse width and the number of NOP instructions between the gpio_clr and gpio_set commands. Sometimes it is 16ns, other times it is nearly a microsecond.
I have tried porting the C code to assembly and it did not change the outcome. Neither did save_and_disable_interrupts(). When placed into a while loop, the first pulse is usually over a microsecond and the other pulses are usually a consistent width.
When I view the disassembly of the C code, there are no instructions between the gpio_clr and gpio_set functions.
I have the impression that the RPI is taking a background action in between the setting and clearing of the pin. I am hoping someone knows how to make this code execute sequentially as it was written.
I would accept an answer that demonstrated how to use a timer channel to provide a single, non-repetitive pulse with 32ns of resolution. The alarm functions seem to have approximately 7us of overhead which makes them unusable.
#include "pico/stdlib.h"
#include "hardware/sync.h"
int main() {
const uint pulse_len = 1;
gpio_init(6);
sio_hw->gpio_set = 1u<<6;
gpio_set_dir(6, GPIO_OUT);
sio_hw->gpio_set = 1u<<6;
uint i=0;
//__asm("cpsid if");
uint32_t istatus = save_and_disable_interrupts();
//provide a single pulse
sio_hw->gpio_clr = 1u<<6;
//__asm("nop"); I would expect each NOP to increase pulse width by the same amount
//__asm("nop");
//__asm("nop");
//__asm("nop");
//__asm("nop");
//__asm("nop");
sio_hw->gpio_set = 1u<<6;
restore_interrupts(istatus);
//__asm("cpsie if");
while(true);
}