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

Softdevice and SPI not Working Together

Hi.

I am working on a project which is using SPI and BLE together.

I wrote SPI code before without soft device. It has simple update function which is sending SPI data. And also i have an timer interrupt which is latching 2 pin high and low. (I need that process every 512uS)

update code below

void tlcUpdate(int number, uint8_t pick)
{

//	__disable_irq();
		NVIC_DisableIRQ(TIMER2_IRQn);

		for(SINData=0;SINData<144;SINData++){
			
			NRF_SPI0->TXD = total[pick][number][SINData];
			
//			while(!(NRF_SPI0->EVENTS_READY));
			
		}
		NVIC_EnableIRQ(TIMER2_IRQn);
//	__enable_irq();
		
}

In first code without softdevice i just use disable_irq() for protecting SPI process. (If an interrupt occur when i deliver my spi data the latching will be active and my led driver will reset for next data. I don't want that so i disable all irq)

void TIMER2_IRQHandler(void)
{

	if ((NRF_TIMER2->EVENTS_COMPARE[1] != 0) && ((NRF_TIMER2->INTENSET & TIMER_INTENSET_COMPARE1_Msk) != 0))
	{
		NRF_TIMER2->EVENTS_COMPARE[1] = 0;
		NRF_GPIO->OUTSET = 18874368;
		NRF_GPIO->OUTCLR = 18874368;
	}
}

This is latching process.

So now, i have softdevice and uart transfer from beacon to mobile app. I think I can't disable all interrupt because of softdevice. So i try to disable just timer2IRQ. It is okay actually my process working but an error accured.

My process normally just take 512uS. But now this time goes up to 2mS. Whenever i use NVIC_Disable my process goes to 2mS. And time is so important for me.

Note : When I call NVIC_disable, while(!(NRF_SPI0->EVENTS_READY))part is not working anymore. I have to close that. (It is working with disable_irq())

Any idea why ? And advice to do ?

Note2 : Actually you maybe do not like my SPI process. I dont use any handler or anything. SDK is 8.1 ( because uart example wont working with SDK12 etc.)

Note3 : NVIC_disable method is working very fine with only spi code(without softdevice) and also no more problem with while(!(NRF_SPI0->EVENTS_READY))part. it is working fine.

Note 4: Also i saw one little more problem. My SCLK is working 8 Mhz but it has %10 duty cycle.. Very weird. ( Without softdevice it is perfect 8Mhz with %100 duty cycle)

I am open for all guidance. I am using ble_app_uart example right now.

My init process.

APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);
		nrf_delay_ms(100);
buttons_leds_init(&erase_bonds);
ble_stack_init();
gap_params_init();
services_init();
advertising_init();
conn_params_init();

//uart_init();

err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
APP_ERROR_CHECK(err_code);
	
		if(err_code != NRF_SUCCESS) nrf_gpio_pin_clear(16);

		
		/**************/
		nrf_gpio_cfg_output(TLC5940_XLAT_PIN);
		nrf_gpio_cfg_output(20);
		nrf_gpio_pin_clear(20);
		nrf_gpio_pin_set(TLC5940_XLAT_PIN);
	
		spi_master_config_t config = SPI_MASTER_INIT_DEFAULT;
		config.SPI_Pin_SCK = SPI0_CONFIG_SCK_PIN;
		config.SPI_Pin_MOSI = SPI0_CONFIG_MOSI_PIN;
		config.SPI_Freq = SPI_FREQUENCY_FREQUENCY_M8;
		config.SPI_CONFIG_ORDER = SPIS_CONFIG_ORDER_MsbFirst;
		config.SPI_CONFIG_CPOL = SPIS_CONFIG_CPOL_ActiveHigh;
		config.SPI_CONFIG_CPHA = SPIS_CONFIG_CPHA_Leading;
		
	
		spi_master_open(SPI_MASTER_0, &config);
	
		startTimer();

startTimer code part (yeah i code like chaos)

void startTimer(void)
{
	/*** GPIOET Set Up Process	***/
	/* Toggle - Pin Number - Initial low output in task mode */
	NRF_GPIOTE->CONFIG[0] = GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos |
													GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos |
													GSCLK << GPIOTE_CONFIG_PSEL_Pos | 
													GPIOTE_CONFIG_OUTINIT_Low << GPIOTE_CONFIG_OUTINIT_Pos;
	/*********************************************************/
	
  NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer;  // Set the timer in Counter Mode
  NRF_TIMER2->TASKS_CLEAR = 1;               // clear the task first to be usable for later
	NRF_TIMER2->PRESCALER = 8;  // Prescaler => 16,000,000 / 256 = 62.5kHz = 16uS 
	NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;//0x01UL;                                                                                                                                                           //Set counter to 16 bit resolution
	NRF_TIMER2->CC[1] = 32;  // 32 x 16uS = 512uS ***This is driver count period***
	
	NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;  // Set the timer in Counter Mode
  NRF_TIMER1->TASKS_CLEAR = 1;               // clear the task first to be usable for later
	NRF_TIMER1->PRESCALER = 0;  // Prescaler => 16,000,000  
	NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_16Bit;//0x01UL;                                                                                                                                                           //Set counter to 16 bit resolution
	NRF_TIMER1->CC[0] = 1;  // Toggle Every Time  16,000,000 / 2 = 8MHz Clock 
	
	// Enable interrupt on Timer 1
//  NRF_TIMER1->INTENSET = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos;                            
  // Enable interrupt on Timer 2
  NRF_TIMER2->INTENSET = TIMER_INTENSET_COMPARE1_Enabled << TIMER_INTENSET_COMPARE1_Pos;

// Clear the timer when Compare0 event is triggered
	NRF_TIMER1->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos;
	// Clear the timer when Compare0 event is triggered
	NRF_TIMER2->SHORTS = TIMER_SHORTS_COMPARE1_CLEAR_Enabled << TIMER_SHORTS_COMPARE1_CLEAR_Pos;
	
  NVIC_EnableIRQ(TIMER2_IRQn);
//	NVIC_EnableIRQ(TIMER1_IRQn);
  
	NRF_TIMER1->TASKS_START = 1;
  NRF_TIMER2->TASKS_START = 1;               // Start timer
	
	/*** Programmable Peripheral Interconnect Set Up Process ***/
	NRF_PPI->CH[0].EEP = (uint32_t) &NRF_TIMER1->EVENTS_COMPARE[0];
	NRF_PPI->CH[0].TEP = (uint32_t) &NRF_GPIOTE->TASKS_OUT[0];

	NRF_PPI->CHENSET = PPI_CHENSET_CH0_Enabled << PPI_CHENSET_CH0_Pos;
	/***********************************************************/
}
Related