This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Interrupts, Timers & SoftDevices

Hi there,

I'm looking at porting (i.e. re-implementing) an Arduino project to the nRF52832 to take advantage of the s212 or S332 softdevices. This chip is a few orders of complexity higher than Arduino, so I expect I've got a steep learning curve ahead of me. This thread was originally going to be a request to help narrow down areas to focus learning on, however, I'm seeing some threads that suggest what I want to do may not be possible on nRF52, due to softdevice interrupts over-riding the interrupts available for use by applications. I'm seeing apparently conflicting threads, though.

The project is an AC power control circuit. I use a TRIAC to suppress the AC sinewave at zero cross for a configurable number of microseconds. This is North American 60 Hz current, so zero cross occurs every 8333-ish microseconds. The TRIAC requires a HIGH pulse of 20 or more microseconds (I use 40) to fire. The current solution uses an optocoupler to generate an interrupt at zero cross. The ISR configures a timer with compare interrupts, with compare register A set to the pre-determined delay 't' ( t < (8333-40) ) and compare register B to t+40 microseconds. The ISR for register A pulls the TRIAC trigger pin HIGH, and the one for register B drops it back to LOW, generating a 40 microsecond pulse.

The delay is calibrated to bicycle speed. The circuit is used to drive a fan, delivering higher power with higher bike speed, simulating wind. At the moment, I am capturing speed on a computer and sending it to the Arduino over USB. I'd like to instead source speed using an ANT+ softDevice on the nRF52832. If I get that working, I'd like to add on a smart phone app, sending configuration data to the fan driver over Bluetooth - so I'm looking at the s332 softdevice.

The existing solution seems to tolerate a variance of +/- 15 microseconds or so on the zero cross interrupt. So there may be some wiggle room for interrupts to be delayed, but I think missing interrupts altogether would wreak havoc. 

I get the impression from some threads that this work might be delegated to PPI/GPIOTE, but the relevant examples still seem to rely on a Timer, which I understand would be still be competing with the Softdevice for interrupts? Thoughts? Am I snookered before I start (having already bought the DK :-( )?

Parents
  • Hi,

    It seems like you can do all the time critical tasks with PPI. You can use the timer and most other peripherals with PPI and/or interrupts. In this case, there does not seem to be any need to generate interrupts at all, so it should not be a problem. You can see the principle demonstrated by the PPI Example.

    The SoftDevice will not cause any problem when no real time CPU involvement is needed. Regardless, you can see the maximum time the SoftDevice will block application interrupts in various roles here (in case it is useful in other scenarios).

  • Hi. Coming back to this problem after some success with the ANT+ PC SDK building the ANT+ emitter for my project. Turning now to the DevKit and building the receiver. I have to say I'm struggling to get a handle on PPI and GPIOTE with the materials I've been able to find. The NRF SDK documentation is, shall we say, 'terse'. The only other pertinent reference I've been able to find is nRF52832 Product Specification, which, obviously is quite detailed, but I think I'm missing some basic fundamentals. I don't think it's fair to ask y'all to try and help me climb this learning curve in this forum.

    I was hoping there might be some other reference material I could be pointed to - especially fundamentals of PPI?

    Failing that, my struggle of the moment is to understand the meaning/ usage of PPI EEPs, TEPs, channels and channel groups. I think it would make sense to me if EEP/TEPs were function pointers, but the SDK defines them as uint32, so that's not holding water. If I'm not firing interrupts and executing ISRs, how do I prescribe the behaviour to occur at timer end?

    Things I need to do:

    1. pull an IO pin HIGH after a calculated number of {100..5000} us and leave it HIGH for 40 us (i.e. deliver a 40 us pulse at the prescribed time)

    2. Programmatic delays of {1..50000} microseconds as part of interfacing to an 16x2 LCD. I haven't found anything ready made so I'm looking to port the Arduino Liquidcrystal lib.

    Lost :-(

  • Hi,

    Conceptually, you can compare PPI with the programmable interconnect you have in FPGAs (there is no programmable logic, though). The event end point (EEP) produces a pulse whenever there is an event. This can then be connected to a PPI channel, which in turn can be connected to a task end point (TEP). When there is a pulse on the task endpoint this triggers the corresponding task. Once configured this happens in HW, without using the CPU at all.

    The SDK itself provides drivers for configuring PPI and the peripherals, but the product specification is the proper place to look for details about PPI, as it is a hardware concept. The following parts of the product specification are useful for understanding PPI:

    I also want to clarify a few things. The end points are nothing like function pointers. They are essentially IDs referring to a physical connection point in the peripheral HW that can be connected together using the programmable interconnect (PPI). Moreover, events are not the same as interrupts. However, interrupts can generate interrupts if interrupts are enabled for that event. The event on the other hand is always generated as long as the condition is met (see the peripheral interface figure).

  • Thanks Einar. I'll take another run at the spec and see if I can figure it out fiddling with the samples. For my second use case, I've seen references to nrf_delay_us(), but the only reference in the SDK is as part of the deprecated TWI driver. Is this an available function? Is there an API doc I'm missing which describes this function? Would it be impacted by the operation of the SoftDevice?

  • Hi Ron,

    The nrf_delay_us() is a software busy wait implementation, so it will essentially consume CPU cycles for the specified amount of time. This means that it will block any same or lower priority interrupts and keep the CPU active, wasting current. So in sum it is primarily only suitable for testing/debugging or waiting for very short durations of time. It has no use in a PPI context. Using an app_timer is probably the best way to wait in SW before triggering some task. It uses the RTC peripheral under the hood which is very power efficient, but has a very simple a flexible API that lets you create an arbitrary number of timers (single shot or repeated). The app_timer is used extensively throughout the SDK.

Reply
  • Hi Ron,

    The nrf_delay_us() is a software busy wait implementation, so it will essentially consume CPU cycles for the specified amount of time. This means that it will block any same or lower priority interrupts and keep the CPU active, wasting current. So in sum it is primarily only suitable for testing/debugging or waiting for very short durations of time. It has no use in a PPI context. Using an app_timer is probably the best way to wait in SW before triggering some task. It uses the RTC peripheral under the hood which is very power efficient, but has a very simple a flexible API that lets you create an arbitrary number of timers (single shot or repeated). The app_timer is used extensively throughout the SDK.

Children
No Data
Related