The finer points of PWM on nRF52 using two chained buffers

I'm looking into a rare issue on the BBC micro:bit V2 which uses the nRF52833 as its (application) microcontroller. I used to be familiar with some CPUs from the 80s but my low-level microcontroller knowledge is very minimal.

There's a two buffer PWM example in https://docs.nordicsemi.com/bundle/ps_nrf52833/page/pwm.html shown in Figure 6. Example using two sequences and described below it.

My first question is what are the options for stopping this once started? Can it be stopped after the current buffer (which could be either SEQ[0] or SEQ[1]) is complete? Can it be stopped after the current sample has been processed? How should it be stopped, is the assignment PWM.TASKS_STOP = 1 enough to stop it and when exactly does this stop it? The code I'm looking at waits for PWM.EVENTS_STOPPED to be non zero to indicate the stop has taken effect.

I see this in the docs.

In this case, an automated playback takes place, consisting of SEQ[0], delay 0, SEQ[1], delay 1, then again SEQ[0], etc. The user can choose to start a complex playback with SEQ[0] or SEQ[1] through sending the SEQSTART[0] or SEQSTART[1] task. The complex playback always ends with delay 1.

Does the sentence I have underlined imply it can only be stopped / will only stop once SEQ[1] is fully processed/complete?


In the nRF52833 errata I'm seeing [183] PWM: False SEQEND[0] and SEQEND[1] events. Under Conditions this says:

Any of the LOOPSDONE_SEQSTARTn shortcuts are enabled. LOOP register is non-zero and sequence 1 is one value long.

Is that saying this definitely only occurs for SEQ[1].CNT = 1? I am far from certain but I think this could explain some issues I'm seeing if it could occur for sequences of length 128 or 8.


Does anyone have any recommendations on detailed tutorials for writing interrupt hanlders in C/C++ for ARMv7 / Cortex M4 / nRF52 / nRF52833? In particular ones that cover what you can do and what you musn't for variables read/written to inside interrupt handler and shared with the rest of the code, i.e. atomicity issues.

  • I've got rid of one issue but another one lurks. I'm getting an EVENT_SEQEND[0] interrupt as the PWM is started back up occasionally. That's clearly bogus because there's 128 samples to process at 800kHz so first one should arrive 160us later.

    I tried adding ENABLE = 0 to the stopping code and that didn't help with this spurious interrupt. I think I may have to implement a workaround in the code to ignore interrupts which happen when the code doesn't think they should.

  • I've now got a problem where a few pulses pop out of a buffer after we would like it to have stopped. I think this is due to a late interrupt. Some of the timings I have seen show little variability and happen to match exactly the duration of both buffers. It seems like a very advanced feature but does the PWM peripheral inside the nRF52 chips have anything that can calculate an imminent second event (in this case 10us later) and then coalesce the two into one slightly later interrupt? This isn't happening all the time, perhaps 1 in 2000 uses of the PWM.

    The comments in the code suggest there's no way to do a reliable STOP after the current buffer has been processed when using LOOP and SHORTS. Is that true? Something like a PWM.EVENT_STOP_AFTER_CURRENT_BUFFER = 1 type thing?

  • Hi,

    Not sure I understand fully, but I guess you can check out the PWM hardware chapter on what may be possible:
    https://docs.nordicsemi.com/bundle/ps_nrf52833/page/pwm.html

    Kenneth

Related