nRF52833 Resets when PWM_CONFIG_LOG_ENABLED is 0

I'm running into an odd problem with the PWM driver.  We're using SDK 17.0.2 and the S113 softdevice on an nRF52833. We're using the PWM module to drive some LEDs.

The nRF52833 will consistently reset without hitting any of the error handlers or printing out any kind of diagnostic over RTT when PWM_CONFIG_LOG_ENABLED is set to 0.  I've tried attaching a debugger to see if any __asm__("BKPT 0"); calls get hit, and none of them get hit.  None of the app_error_x functions (like app_error_fault_handler) get called either.  The board is being powered from a Segger J-Link and the voltage rails are rock solid, so it's not a power glitch.  It's always resetting in a call to nrfx_pwm_stop.

The nRF52833 will be up and running for a little bit of time (a few seconds to a minute) when the reset happens.

But the system becomes 100% stable when PWM_CONFIG_LOG_ENABLED is set to 1, which (I think) says there's a timing issue somewhere. 

Parents
  • Hello,

    I am sorry for the late reply. 

    I tested the pwm_driver with the armgcc compiler and the nRF52833 DK from SDK17.0.2 with PWM_CONFIG_LOG_ENABLED set to 0, and I didn't encounter any issues. I just used the unmodified pwm_driver example from SDK\examples\peripheral\pwm_driver, and I copied the pca10056 folder, renamed it pca10100, and then changed all occurrences of nrf52840 to nrf52833 and all occurrences of pca10056 to pca10100 in the makefile, and I changed the RAM and FLASH sizes to half of the default values in the pwm_driver_gcc_nrf52.ld in pca10100\blank\armgcc.

    I don't know what project you started out with, since you are using the s113 softdevice, or what IDE you are using, but perhaps you can zip and send me the project folder, so that I can have a look?

    In case you are interested in testing the project that I tested, you can find it here:

    NB: I only modified the armgcc compiler folder, and not the Keil, SES, or IAR projects. 

    BR,
    Edvin

  • Hi Edvin,

    Thanks for that sample application.  I think I see the problem now.  nrfx_pwm_init is sometimes returning NRF_ERROR_INVALID_STATE, and our code is ignoring that return value, so it calls straight into nrfx_pwm_simple_playback, which is causing the reboot.  It was hidden in the log output by a bunch of "nrfx_pwm_is_stopped returned 0" outputs while the code waited for the PWM to stop. 

    Edit with more information:

    We are using the PWM driver to run RGB LEDs that indicate the state of the system.  In order to change what the LEDs were showing, we would call nrfx_pwm_stop in the mainline code, and call nrfx_pwm_uninit in the nrfx_pwm_handler_t, that's passed to nrfx_pwm_init.

    This was causing a concurrency problem, where sometimes nrfx_pwm_init and nrfx_pwm_simple_playback were getting called before nrfx_pwm_uninit was getting called.

    Here's some really basic example code.

    /******************************************************************************
    * Unititializes the pwm driver on stop.
    *******************************************************************************/
    void PWM_Handler(nrf_drv_pwm_evt_type_t eventType)
    {
      if (eventType == NRF_DRV_PWM_EVT_FINISHED || eventType == NRF_DRV_PWM_EVT_STOPPED)
      {
        nrfx_pwm_uninit(&pwm);
      }
    }
    
    /******************************************************************************
    * Inits and starts the requested animation based on the state
    *******************************************************************************/
    void PWM_RunAnimation(LEDState_T *state)
    {
        currentState = state;
        currentState->isActive = true;
        nrfx_pwm_init(&pwm, &state->config, PWM_Handler);
        nrfx_pwm_simple_playback(&pwm, &state->sequence, state->playbacks, NRFX_PWM_FLAG_STOP);
    }
    
    /******************************************************************************
    * Stops the requested animation based on the state
    *******************************************************************************/
    void PWM_StopAnimation()
    {
        nrfx_pwm_stop(&pwm, true);
    }
    
    /******************************************************************************
    * Updates the LED state
    *******************************************************************************/
    void PWM_UpdateState()
    {
       PWM_StopAnimation();
       PWM_RunAnimation(&animations[index]);
    }

    The entrance to this code is in PWM_UpdateState().  It stops the current animation and starts the next animation.  The first thing it does is call PWM_StopAnimation, which triggers the stop sequence.  BUT it takes time for the stop sequence to happen, meanwhile the running code is in PWM_RunAnimation. 

    The callback to PWM_Handler usually took more time than it took for the code to run through PWM_RunAnimation with the PWM logging disabled.  With PWM logging enabled, it would usually take longer for the logging code to run, giving maybe enough time for the callback to be called.

    I fixed this by calling nrfx_pwm_uninit in PWM_StopAnimation.

Reply
  • Hi Edvin,

    Thanks for that sample application.  I think I see the problem now.  nrfx_pwm_init is sometimes returning NRF_ERROR_INVALID_STATE, and our code is ignoring that return value, so it calls straight into nrfx_pwm_simple_playback, which is causing the reboot.  It was hidden in the log output by a bunch of "nrfx_pwm_is_stopped returned 0" outputs while the code waited for the PWM to stop. 

    Edit with more information:

    We are using the PWM driver to run RGB LEDs that indicate the state of the system.  In order to change what the LEDs were showing, we would call nrfx_pwm_stop in the mainline code, and call nrfx_pwm_uninit in the nrfx_pwm_handler_t, that's passed to nrfx_pwm_init.

    This was causing a concurrency problem, where sometimes nrfx_pwm_init and nrfx_pwm_simple_playback were getting called before nrfx_pwm_uninit was getting called.

    Here's some really basic example code.

    /******************************************************************************
    * Unititializes the pwm driver on stop.
    *******************************************************************************/
    void PWM_Handler(nrf_drv_pwm_evt_type_t eventType)
    {
      if (eventType == NRF_DRV_PWM_EVT_FINISHED || eventType == NRF_DRV_PWM_EVT_STOPPED)
      {
        nrfx_pwm_uninit(&pwm);
      }
    }
    
    /******************************************************************************
    * Inits and starts the requested animation based on the state
    *******************************************************************************/
    void PWM_RunAnimation(LEDState_T *state)
    {
        currentState = state;
        currentState->isActive = true;
        nrfx_pwm_init(&pwm, &state->config, PWM_Handler);
        nrfx_pwm_simple_playback(&pwm, &state->sequence, state->playbacks, NRFX_PWM_FLAG_STOP);
    }
    
    /******************************************************************************
    * Stops the requested animation based on the state
    *******************************************************************************/
    void PWM_StopAnimation()
    {
        nrfx_pwm_stop(&pwm, true);
    }
    
    /******************************************************************************
    * Updates the LED state
    *******************************************************************************/
    void PWM_UpdateState()
    {
       PWM_StopAnimation();
       PWM_RunAnimation(&animations[index]);
    }

    The entrance to this code is in PWM_UpdateState().  It stops the current animation and starts the next animation.  The first thing it does is call PWM_StopAnimation, which triggers the stop sequence.  BUT it takes time for the stop sequence to happen, meanwhile the running code is in PWM_RunAnimation. 

    The callback to PWM_Handler usually took more time than it took for the code to run through PWM_RunAnimation with the PWM logging disabled.  With PWM logging enabled, it would usually take longer for the logging code to run, giving maybe enough time for the callback to be called.

    I fixed this by calling nrfx_pwm_uninit in PWM_StopAnimation.

Children
No Data
Related