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

nRF52832 use PPI to control an output pin GPIOTE

I am trying to use PPI to control an output pin. I am successfully using 2 PPI channels at the moment to use the COMP to do freq counting over a 10mS time period. I have added a 3rd PPI channel to turn an output off in below code.

static void ppi_init(void)
{
    uint32_t err_code = NRF_SUCCESS;

    err_code = nrf_drv_ppi_init();
    error_check(err_code);

    err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);

    //Configure GPIOTE
    nrf_drv_gpiote_out_config_t config = NRFX_GPIOTE_CONFIG_OUT_TASK_LOW; //TOGGLE(NRF_GPIOTE_INITIAL_VALUE_HIGH);//
    err_code = nrf_drv_gpiote_out_init(MI_EN, &config);
    APP_ERROR_CHECK(err_code);
    uint32_t gpiote_task_addr = nrf_drv_gpiote_out_task_addr_get(MI_EN);
    nrf_drv_gpiote_out_task_enable(MI_EN);

    /* Configure 1st available PPI channel to count timer1 when comp has UP event
     */
    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel1);
    error_check(err_code);
    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel1, 0x40013108, 0x40009008);
    error_check(err_code);
    //0x40013108 = Comp UP event
    //0x40009008 = Timer 1 Count

        /* Configure 2nd available PPI channel to stop TIMER1 (counter) counting when timer 2 ticks
     */
    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel2);
    error_check(err_code);
    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel2,
                                          nrf_drv_timer_event_address_get(&m_timer4,
                                                                          NRF_TIMER_EVENT_COMPARE0),
                                          nrf_drv_timer_task_address_get(&m_timer1,
                                                                         NRF_TIMER_TASK_STOP));
    error_check(err_code);

    /* Configure 3rd available PPI channel to set MI-EN low after compare event
     */
    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel3);
    error_check(err_code);
    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel3,
                                          nrf_drv_timer_event_address_get(&m_timer4,
                                                                          NRF_TIMER_EVENT_COMPARE0),
                                          gpiote_task_addr);

    error_check(err_code);

    // Enable both configured PPI channels
    err_code = nrf_drv_ppi_channel_enable(m_ppi_channel1);
    error_check(err_code);
    err_code = nrf_drv_ppi_channel_enable(m_ppi_channel2);
    error_check(err_code);
    err_code = nrf_drv_ppi_channel_enable(m_ppi_channel3);
    error_check(err_code);
}

/** @brief Function for Timer 1 initialization.
 *  setup as a counter
 */
static void timer1_init(void)
{
    // Check TIMER1 configuration for details.
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.frequency = NRF_TIMER_FREQ_31250Hz;
    timer_cfg.mode = NRF_TIMER_MODE_COUNTER;
    
    ret_code_t err_code = nrf_drv_timer_init(&m_timer1, &timer_cfg, NULL);
    error_check(err_code);
}

Then I have a seperate RTC timer at 32Hz, that resets the timers and sets the output pin high.

   //capture the counter value
   MI_freq = nrf_drv_timer_capture(&m_timer1, 0);

   //Restart the timers for the PPI MI capture
   nrf_drv_timer_enable(&m_timer1);
   nrf_drv_timer_enable(&m_timer4);
   nrf_drv_timer_clear(&m_timer1);
   nrf_drv_timer_clear(&m_timer4);

   //Set the output high
   nrf_drv_gpiote_out_set(MI_EN);

The output is always off. If I set the task type to GPIOTE TASK_HIGH then the output is always on.

Is there anything obviously wrong in the code? My timers / counter and PPI channel 1 and 2 are all working as expected.

It appears as if the GPIOTE task is always running, i.e. holding the output low all the time and not just triggering on the PPI timer compare.

Thanks 

  • Hi,

    The output is always off. If I set the task type to GPIOTE TASK_HIGH then the output is always on.

     If you configure the GPIOTE output to TASK_HIGH, then the transaction is from low-to-high on the event (configured via PPI):

    /**@brief Macro for configuring a pin to use the GPIO OUT TASK to change the state from low to high.
     * @details The task will set the pin. Therefore, the pin is cleared initially.  */
    #define NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH            \
        {                                               \
            .init_state = NRF_GPIOTE_INITIAL_VALUE_LOW, \
            .task_pin   = true,                         \
            .action     = NRF_GPIOTE_POLARITY_LOTOHI,   \
        }

    And the other way around when you configure with TASK_LOW, ie event will set the pin low:

    /**@brief Macro for configuring a pin to use the GPIO OUT TASK to change the state from high to low.
     * @details The task will clear the pin. Therefore, the pin is set initially.  */
    #define NRFX_GPIOTE_CONFIG_OUT_TASK_LOW              \
        {                                                \
            .init_state = NRF_GPIOTE_INITIAL_VALUE_HIGH, \
            .task_pin   = true,                          \
            .action     = NRF_GPIOTE_POLARITY_HITOLO,    \
        }

     

    Are you toggling the pin somewhere else in your program? If not, it will only occur once, and be kept in that state for the rest of the runtime.

    You could try to set "NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE" to see if the pin itself toggles? just to see if the logic behind works as it should.

     

    Kind regards,

    Håkon

  • Hi 

    Yes I set it high along with reseting the timers 32 times a second (see second code section).

    //Set the output high
    nrf_drv_gpiote_out_set(MI_EN);

    If I do toggle the pin does toggle ok.

    Phil

  • Hi Phil,

     

    Philip said:
    If I do toggle the pin does toggle ok.

     This is good. The "logic underneath" works as it should 

    Philip said:
    nrf_drv_gpiote_out_set(MI_EN);

     Could you try to call "nrf_drv_gpiote_set_task_trigger" instead?

     

    Kind regards,

    Håkon

  • Hi Håkon,

    That worked! Thanks.

    Getting a 10mS On pulse now at 32Hz.

    Phil

Related