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;
	/***********************************************************/
}
Parents
  • You have written your own SPI "driver" directly on top of nRF5x register "HAL" but that won't work out of the box when Soft Device is running. All that is explained in Soft Device specification but in short you will need to use task&event mechanisms and do all things asynchronously, nothing like writing to GPIO registers in interrupt handler or similar simplifications (that can work on Arduino or similar simple MCU but not on SoC running "real time" radio stack). Any reason why you haven't used Nordic SPI driver from SDK which works with Soft Device flowlessly?

  • Because I can't use that complicated example code as well as basic simplification :)

    Anyway, when i first tried Nordic SPI driver, i just reach 1.4mS speed for transaction. Maybe i used that wrong but that is it. My "driver like to be" is just transfer all data in 160uS. (I really do not know how but i don't have any other error or control mechanism. Just pushing all data to TXD)

    So I need fast transmission.

Reply
  • Because I can't use that complicated example code as well as basic simplification :)

    Anyway, when i first tried Nordic SPI driver, i just reach 1.4mS speed for transaction. Maybe i used that wrong but that is it. My "driver like to be" is just transfer all data in 160uS. (I really do not know how but i don't have any other error or control mechanism. Just pushing all data to TXD)

    So I need fast transmission.

Children
No Data
Related