Using PCA 10040A , SDK 16.0.0 and Segger Studio.
I would like to generate a short accurate *** on a GPIO , probably 250 nano seconds duration. So I am looking at using the GPIOTE feature.
However I need to keep the GPIO drive configuration as
"NRF_GPIO_PIN_D0S1 = GPIO_PIN_CNF_DRIVE_D0S1, ///< !< Disconnect '0' standard '1'."
So that when its low there is no drive its effectively Open Collector
The GPIOTE doc says that it takes over the GPIO and it says "When the GPIOTE is disconnected from a pin, see MODE field in CONFIG[n] register, the associated pin will get the output and configuration values specified in the GPIO module."
This suggests that my drive configuration maybe changed by the GPIOTE module
Can someone confirm this please and if its correct can anyone suggest an alternative to using the GPIOTE/PPI feature
We need to generate a precise pulse on a GPIO in nanoseconds that is with 16MHZ clock 62.5ns resolution , will typically be multiples of this.
I was thinking of using the GPIOTE to get the precision, however the GPIO being used is configured as
So effectively Open Collector when LOW we need the GPIO to be in this state when LOW.
When you configure the GPIOTE it takes over the GPIO and the configuration no longer applies.
We need to take the HIGH GPIO for a precise period and then return to the LOW Disconnected state when finished.
Any ideas how we can do this, I did think of using a timer but reading other posts there is a lot of inaccuracy in doing it that way
You should be able to change drive settings even if the GPIOTE module is connected to a pin.
If you look at figure 1 here you can see that there are OVERRIDE signals for pin direction, out pin state and input connection, allowing peripherals such as the GPIOTE module to override the settings you configure, but DRIVE settings are not covered by this.
In other words the drive settings should still be available for you to change.
If you are having issues getting this to work let me know, and I will have a look.
Thanks for that clarification I wanted to make sure the drive stays the same when the GPIOTE takes over.
Also I need to generate a pulse period in nanoseconds, I assume with 16Mhz clock that will be a minimum pulse of 62.5ns , can you provide some insight how I should do that ? I see from all the examples there are functions to convert ms and us to ticks but nothing smaller.
Also I want to make sure nothing affects this timing , what should I disable etc while I am waiting for the event to indicate its completed.
If you write to the CC registers in the TIMER module you can decide exactly how many timer pulses should elapse before the corresponding COMPARE event should be generated, and use this to set or clear the pin through the GPIOTE.
TIMER3 and 4 have a total of 6 CC registers, allowing you to prepare 6 such events ahead of time.
Assuming the PRESCALER register is set to 0 each count will equal 62.5ns, as you say.
For a sample of how to write to the TIMER, PPI and GPIOTE registers you can have a look at the following function.
Thank you for your help this is starting to make sense and will save me a lot of time. So its looks like the best way for me to generate a short pulse , say 250ns, would be to have 2 timers connected to one gpiote , the first timing isnt critical it would be used to take the GPIO high and then second timer would be the critical one and this would take the GPIO LOW.
I assume I would set the timers up as NRF_TIMER_SHORT_COMPARE0_STOP_MASK and that I would need to enable interrupts by setting the parameter true in "nrfx_timer_extended_compare(...)" for the 2nd timer only so I knew that it had completed.
Are there any similar examples I could look at for the above.
I did try playing with the "gpiote" example provided that toggles one GPIO every 200ms.I changed NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK to NRF_TIMER_SHORT_COMPARE0_STOP_MASK in the function led_blinking_setup() and enabled interrupts in the "nrf_drv_timer_extended_compare()" function call.I then expected to see the GPIO toggle hi then low for the period I had selected, but all I saw on my scope was the GPIO going high and staying high. Why doesnt this work ?
If you replace the CLEAR mask with the STOP mask it means you have to clear and restart the timer manually for each pulse.
I think a better approach is to use two CC registers on the timer: One to raise the pin immediately (or after 1 tick), and a second one to clear it.
Then you can use shortcuts to stop and clear the timer after the second compare event, and simply start the timer every time you want a pulse to be generated.
Starting a timer can be done either manually by the CPU, or through a PPI channel from some other peripheral.
I modified the gpiote example to illustrate the software method:
Great this is what I need, i assume I will need to set the interrupt enable parameter (the last param) in the 2nd call to nrf_drv_timer_extended_compare() so that the "timer_dummy_handler()" function is called when the 2nd event occurs and I will know the pulse has completed.
Also I will want to change the period of the pulse, so once this is all setup can i simply call nrf_drv_timer_extended_compare(&timer, (nrf_timer_cc_channel_t)1, 1 + LED_ON_TICKS, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK | NRF_TIMER_SHORT_COMPARE1_STOP_MASK, false);
again but with a new time period ?
And then use nrf_drv_timer_resume() to start it again with the new time period for the 2nd compare
Yes, if you want a callback after the pulse is complete you should enable interrupts as you describe. This will happen more or less immediately if you set the pulse length to 250ns ;)
Yes, this should work fine.