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

PPI acts strange with more than 2 PPI channels

While using PPI and trying to use the first channel as a clock based PWM running on timer1 I noticed that whenever I use more than 2 PPI channels, the pin that is toggeling on timer1 goes to a much higher frequency (2 Hz to 2kHz). Moreover the LEDs that are on a PPI channel and supposed to react to the first channel toggling from high to low stay off but when measured I get a voltage of 3,3 on the LEDs. But im wondering why the PPI acts this way as I was only using two channels. The code I used to initialize the PPI setup that works when I comment out ppi_set_led2 or 3:

#include "ppi_setup.h"

#define LED1 21
#define LED2 22
#define LED3 23

#define SENSE1 10
#define SENSE2 11

//Declare PPI channels
nrf_ppi_channel_t ppi_channel1;
nrf_ppi_channel_t ppi_channel2;
nrf_ppi_channel_t ppi_channel3;

//Declare Timer
const nrf_drv_timer_t timer1 = NRF_DRV_TIMER_INSTANCE(0);

void ppi_init(void)
{
	ppi_set_LED1();
	ppi_set_LED2();
	//ppi_set_LED3();
	
	nrf_drv_timer_enable(&timer1);
}

void ppi_set_LED1(void)
{
	//Declare Variables
	uint32_t err_code;
	uint32_t led1_task_addr;
	
	//Configure Task & Event
	nrf_drv_gpiote_out_config_t led1_output_config 	= GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
	
	//Initialize peripherals
	err_code = nrf_drv_gpiote_out_init(LED1, &led1_output_config);
	APP_ERROR_CHECK(err_code);
	
	//Set timer compare trigger
	nrf_drv_timer_extended_compare(&timer1, (nrf_timer_cc_channel_t)0, 0x0000F424, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
	
	//Set Task & Event pointers
	led1_task_addr 	= nrf_drv_gpiote_out_task_addr_get(LED1);
	
	//Allocate PPI channel
	err_code 						= nrf_drv_ppi_channel_alloc(&ppi_channel1);
	APP_ERROR_CHECK(err_code);
	
	//Assign Event-End-Point (EEP) and Task-Event-Point (TEP)
	err_code = nrf_drv_ppi_channel_assign(ppi_channel1, nrf_drv_timer_event_address_get(&timer1, NRF_TIMER_EVENT_COMPARE0), led1_task_addr);
	
	//Enable PPI channel & peripherals
	err_code = nrf_drv_ppi_channel_enable(ppi_channel1);
	APP_ERROR_CHECK(err_code);

	nrf_drv_gpiote_out_task_enable(LED1);
}

void ppi_set_LED2(void)
{
	//Declare Variables
	uint32_t err_code = NRF_SUCCESS;
	
	uint32_t led2_event_addr;
	uint32_t led2_task_addr;
	
	//Configure Task & Event
	nrf_drv_gpiote_in_config_t  led2_event_config	= GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
	nrf_drv_gpiote_out_config_t led2_task_config	= GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);	
	
	//Initialize peripherals
	err_code = nrf_drv_gpiote_in_init(SENSE1, &led2_event_config, false);
	APP_ERROR_CHECK(err_code);
 
	err_code = nrf_drv_gpiote_out_init(LED2, &led2_task_config);
	APP_ERROR_CHECK(err_code);
	

	//Set Task & Event pointers
	led2_event_addr	=	nrf_drv_gpiote_in_event_addr_get(SENSE1);
	led2_task_addr	=	nrf_drv_gpiote_out_task_addr_get(LED2); 
	
	//Allocate PPI channel
	err_code 						= nrf_drv_ppi_channel_alloc(&ppi_channel2);
	APP_ERROR_CHECK(err_code);
	
	//Assign Event-End-Point (EEP) and Task-Event-Point (TEP)
	err_code = nrf_drv_ppi_channel_assign(ppi_channel2, led2_event_addr, led2_task_addr);
	//Enable PPI channel & peripherals
	err_code = nrf_drv_ppi_channel_enable(ppi_channel2);
	APP_ERROR_CHECK(err_code);

	nrf_drv_gpiote_in_event_enable(SENSE1, false);
	nrf_drv_gpiote_out_task_enable(LED2);
}

void ppi_set_LED3(void)
{
	//Declare Variables
	uint32_t err_code = NRF_SUCCESS;
	
	uint32_t led3_event_addr;
	uint32_t led3_task_addr;
	
	//Configure Task & Event
	nrf_drv_gpiote_in_config_t  led3_event_config	= GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
	nrf_drv_gpiote_out_config_t led3_task_config	= GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);	
	
	//Initialize peripherals
	err_code = nrf_drv_gpiote_in_init(SENSE2, &led3_event_config, false);
	APP_ERROR_CHECK(err_code);
 
	err_code = nrf_drv_gpiote_out_init(LED3, &led3_task_config);
	APP_ERROR_CHECK(err_code);
	

	//Set Task & Event pointers
	led3_event_addr	=	nrf_drv_gpiote_in_event_addr_get(SENSE2);
	led3_task_addr	=	nrf_drv_gpiote_out_task_addr_get(LED3); 
	
	//Allocate PPI channel
	err_code 						= nrf_drv_ppi_channel_alloc(&ppi_channel3);
	APP_ERROR_CHECK(err_code);
	
	//Assign Event-End-Point (EEP) and Task-Event-Point (TEP)
	err_code = nrf_drv_ppi_channel_assign(ppi_channel3, led3_event_addr, led3_task_addr);
	//Enable PPI channel & peripherals
	err_code = nrf_drv_ppi_channel_enable(ppi_channel3);
	APP_ERROR_CHECK(err_code);

	nrf_drv_gpiote_in_event_enable(SENSE2, false);
	nrf_drv_gpiote_out_task_enable(LED3);
}

The main code:

#include "nrf.h"
#include "app_error.h"
#include "bsp.h"
#include "nrf_delay.h"
#include "nrf_gpio.h"
#include "nrf_gpiote.h"
#include "app_pwm.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_timer.h"
#include "nrf_drv_gpiote.h"
#include "boards.h"
#include "nrf_soc.h"
#include "ppi_setup.h"

static void power_manage(void);
	
static void power_manage(void)
{
    uint32_t err_code = sd_app_evt_wait();
    APP_ERROR_CHECK(err_code);
}
int main(void)
{	
	ret_code_t err_code;

	err_code = nrf_drv_ppi_init();
	APP_ERROR_CHECK(err_code);

	err_code = nrf_drv_gpiote_init();
	APP_ERROR_CHECK(err_code);

	NRF_POWER->TASKS_CONSTLAT = 1;

	NRF_TIMER0->PRESCALER 	= 8;
	NRF_TIMER0->TASKS_CLEAR = 1;
	
	ppi_init();
	
	while(true)
	{
		power_manage();
	}
}
Parents
  • nrf_drv_gpiote_out_init(LED3, &led3_task_config) is returning error code 0x04 which is NRF_ERROR_NO_MEM. nRF51 only have 4 GPIOTE channels and before calling nrf_drv_gpiote_out_init(LED3, &led3_task_config) all have been used. You should rather use (also for led 2 input):

    nrf_drv_gpiote_in_config_t  led3_event_config   = GPIOTE_CONFIG_IN_SENSE_LOTOHI(false);
    

    which do not use GPIOTE channel, but a SENSE mechanism in the GPIO peripheral. This has lower accuracy, but uses less power and are only limited by the number of pins in hardware. In the driver it is limited by the macro GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS, make sure this is high enough.

    I advice you to use pullup on the input if these are floating when not active:

    led3_event_config.pull = NRF_GPIO_PIN_PULLUP;
    

    I will also advice you to read this post on debugging.

  • So setting the macro turned on the LEDs that stayed off but I've been looking around but I can't find out how to use:

    nrf_drv_gpiote_in_config_t  led3_event_config   = GPIOTE_CONFIG_IN_SENSE_LOTOHI(false);
    

    the nrf_drv_gpiote_in_config_t as an event in the PPI channels.

Reply Children
No Data
Related