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

52832 spim data error

Now I use sdk15.2.0 hrs project to add the spim.

the mode of the spi is timer+ppi+spi.

question:1.I can't enter the led_timer_handler on time;2.I can't get the right data,when I enable the ble advertise.

Parents
  • no you're going to need to ask a much better question than this with proper details if you expect anyone to be able to help you. 

  • OK,thank you.

    my demon code like this.I use spim to read data from the external ADC.

    void my_ppi_init(void)
    {
    	uint32_t err_code = NRF_SUCCESS;
    
    	err_code = nrf_drv_ppi_init();//init PPI
    	APP_ERROR_CHECK(err_code);
    
    	err_code = nrf_drv_timer_init(&m_timer1, NULL, timer_handler1);//init timer 1
    	APP_ERROR_CHECK(err_code);
    
    	/* setup m_timer for compare event every 15us */
    	uint32_t ticks = nrf_drv_timer_us_to_ticks(&m_timer1, 15);
    	nrf_drv_timer_extended_compare(&m_timer1, NRF_TIMER_CC_CHANNEL0, ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);//Setting comparison events
    	nrf_drv_timer_enable(&m_timer1);
    
    	uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer1, NRF_TIMER_CC_CHANNEL0);
    	uint32_t spi_start_event_addr = nrf_drv_spi_start_task_get(&spi);
    	uint32_t spi_end_event_addr = nrf_drv_spi_end_event_get(&spi);
    	uint32_t gpiote_out_event_addr = nrf_drv_gpiote_out_task_addr_get(SPI_SS_PIN);
    	/* setup ppi channel so that timer compare event is triggering sample task in SAADC */
    	err_code = nrf_drv_ppi_channel_alloc(&time_ppi_channel);
    	APP_ERROR_CHECK(err_code);
    	
    	err_code = nrf_drv_ppi_channel_assign(time_ppi_channel, timer_compare_event_addr, gpiote_out_event_addr);
    	APP_ERROR_CHECK(err_code);
    	err_code=nrf_drv_ppi_channel_fork_assign(time_ppi_channel,spi_start_event_addr);
    	APP_ERROR_CHECK(err_code);
    	
    	err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
    	APP_ERROR_CHECK(err_code);
    	
    	err_code = nrf_drv_ppi_channel_assign(m_ppi_channel, spi_end_event_addr, gpiote_out_event_addr);
    	APP_ERROR_CHECK(err_code);
    	
    	err_code = nrf_drv_ppi_channel_enable(time_ppi_channel);
      APP_ERROR_CHECK(err_code);
    	err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
      APP_ERROR_CHECK(err_code);
    }
    
    void spi_event(nrf_drv_spi_evt_t const * p_event,
                           void *                    p_context)
    {		
    	spi_count++;
    	if(spi_count==data_num)
    	{
    		spi_count=0; 
    		
    		NRF_SPIM0->TXD.PTR=(uint32_t)&SPIWriteList;
    		NRF_SPIM0->RXD.PTR=(uint32_t)&SPIReadList1;
    		send_flag = 1;
    	}
    }
    
    void CS_Gpiote_Init(void) { 
    	uint32_t err_code; //???GPIOTE???? 
    	
    	err_code = nrf_drv_gpiote_init(); 
    	APP_ERROR_CHECK(err_code); 
    	
    	nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true); //???GPIOTE????,?????????GPIOTE?? 
    	err_code = nrf_drv_gpiote_out_init(SPI_SS_PIN, &config); 
    	APP_ERROR_CHECK(err_code); //???? ??GPIOTE??????? 
    	
    	nrf_drv_gpiote_out_task_enable(SPI_SS_PIN); 
    	nrf_drv_gpiote_out_set(SPI_SS_PIN); 
    }
    
    void ADC_SPIDMA_Init (void) 
    { 
    	uint8_t i=0;
    	uint8_t j=0;
    	uint8_t temp_H,temp_L; 
    	
    	NRF_SPIM0->TXD.MAXCNT = 2;  
    	NRF_SPIM0->TXD.LIST=1; 
    	NRF_SPIM0->TXD.PTR=(uint32_t)SPISeletList; 
    	NRF_SPIM0->RXD.MAXCNT = 2;
    	NRF_SPIM0->RXD.LIST=1; 
    	NRF_SPIM0->RXD.PTR=(uint32_t)SPIReadList1;  
    }
    
    void ad7689_spi_init(void)
    {
    	nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
    //	spi_config.ss_pin   = SPI_SS_PIN;
    	spi_config.miso_pin = SPI_MISO_PIN;
    	spi_config.mosi_pin = SPI_MOSI_PIN;
    	spi_config.sck_pin  = SPI_SCK_PIN;
    	APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event, NULL));
    	CS_Gpiote_Init();
    	ADC_SPIDMA_Init();
    }
    
    void ad7689_readdata(uint16_t *buff)
    {
    		uint8_t i=0;
    		uint16_t tmp=0;
    	
    		for(i=0;i<85;i++)
    		{
    			tmp=SPIReadList1[i].buffer[0];
    			buff[i]=(tmp<<8)|SPIReadList1[i].buffer[1];
    		}
    }

    but I find that if I only enable "NRF_SPIM0->TXD.LIST" like this code,the ble can run on right way(the leds_timer_handler can callback on time,the app can search the device).but I can't read the ADCdata.

    void ADC_SPIDMA_Init (void) 
    {
        ……
        NRF_SPIM0->TXD.MAXCNT = 2; 
        NRF_SPIM0->TXD.LIST=1; 
        NRF_SPIM0->TXD.PTR=(uint32_t)SPISeletList; 
        ……
    }
    
    void spi_event(nrf_drv_spi_evt_t const * p_event,
                           void *                    p_context)
    {		
    	spi_count++;
    	if(spi_count==data_num)
    	{
    		spi_count=0; 
    		
    		NRF_SPIM0->TXD.PTR=(uint32_t)SPIWriteList;
    //		NRF_SPIM0->RXD.PTR=(uint32_t)SPIReadList1;
    		send_flag = 1;
    	}
    }
    

    SO I use next code,I enable "NRF_SPIM0->TXD.LIST" and "NRF_SPIM0->RXD.LIST".but the ble can't run on right way(the leds_timer_handler can't callback on time,the led always light).

    and the SPI data have some wrong data.if I close ble advertise ,I can get the right data throught serial port

    void ADC_SPIDMA_Init (void) 
    { 
    	uint8_t i=0;
    	uint8_t j=0;
    	uint8_t temp_H,temp_L; 
    	
    	NRF_SPIM0->TXD.MAXCNT = 2;  
    	NRF_SPIM0->TXD.LIST=1; 
    	NRF_SPIM0->TXD.PTR=(uint32_t)SPISeletList; 
    	NRF_SPIM0->RXD.MAXCNT = 2;
    	NRF_SPIM0->RXD.LIST=1; 
    	NRF_SPIM0->RXD.PTR=(uint32_t)SPIReadList1;  
    }
    
    void spi_event(nrf_drv_spi_evt_t const * p_event,
                           void *                    p_context)
    {		
    	spi_count++;
    	if(spi_count==data_num)
    	{
    		spi_count=0; 
    		
    		NRF_SPIM0->TXD.PTR=(uint32_t)SPIWriteList;
    		NRF_SPIM0->RXD.PTR=(uint32_t)SPIReadList1;
    		send_flag = 1;
    	}
    }

    question:1.Is the way I use SPI correct?if wrong,please give me a demon code;

                      2. why I close the ble advertise,I can get the right data throught serial port?

  • Hi.

    I would not recommend that you use the SPI driver while also accessing the registers manually, this is bound to give you trouble.

    How do you define the buffers you use? (SPISeletList, SPIReadList1, SPIWriteList)

    How ofter do you read the ADC? Very high frequency could give you trouble with BLE. If you have a low frenquency you might not need the list function.

    I would recommend that you take a look at the example found in examples\peripheral\spi\main.c for the SPI driver.

    Best regards,

    Andreas

Reply
  • Hi.

    I would not recommend that you use the SPI driver while also accessing the registers manually, this is bound to give you trouble.

    How do you define the buffers you use? (SPISeletList, SPIReadList1, SPIWriteList)

    How ofter do you read the ADC? Very high frequency could give you trouble with BLE. If you have a low frenquency you might not need the list function.

    I would recommend that you take a look at the example found in examples\peripheral\spi\main.c for the SPI driver.

    Best regards,

    Andreas

Children
  • thank you ,AndreasF.

    1.SPI driver code like this,it's same as me to set register.

    __STATIC_INLINE void nrf_spim_tx_buffer_set(NRF_SPIM_Type * p_reg,
                                                uint8_t const * p_buffer,
                                                size_t          length)
    {
        p_reg->TXD.PTR    = (uint32_t)p_buffer;
        p_reg->TXD.MAXCNT = length;
    }

           

      I define these buffer like this

    typedef struct ArrayList
    {
        uint8_t buffer[2];
    }ArrayList_type;

               the frequence to read ADC is about 64Khz,so I set timer1 about 15us to trigger the ADC read

  • Hi again.

     

    NORDIC_SUR said:
    1.SPI driver code like this,it's same as me to set register.

     Why don't you use the driver then? When you mix up registers and drivers the chance of having bugs increase and it is really hard to read your code. Are you trying to implement something that the driver does not support, since you want to mix the driver usage with your own implementation.

     

    NORDIC_SUR said:

    I define these buffer like this

     the frequence to read ADC is about 64Khz,so I set timer1 about 15us to trigger the ADC read

     64 kHz is quick, you should set up 64 buffers so that you can read data once each millisecond.

    Best regards,

    Andreas

  • Hi, AndreasF.

                 now I try to use the spi driver to read data.I use some code like this.

    s8 bmi160_bus_burst_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u32 cnt)
    {
        m_tx_buf[0] = reg_addr | READ_MASK;
    
        nrf_drv_spi_xfer_desc_t xfer = NRF_DRV_SPI_XFER_TRX(m_tx_buf, 1, reg_data, 255);
        uint32_t flags = NRF_DRV_SPI_FLAG_HOLD_XFER |
                         NRF_DRV_SPI_FLAG_REPEATED_XFER |
                         NRF_DRV_SPI_FLAG_RX_POSTINC  |
                         NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER;
        nrf_drv_spi_xfer(&spi, &xfer, flags);  
    
        burst_transfer_enable();
    
        nrf_spim_task_trigger(spi.p_registers, NRF_SPIM_TASK_START);
    
        while(!burst_completed){
            __WFE();
        }
        spi_xfer_done = false;
        burst_completed = false;
    
        return SUCCESS;
    }

    but I have some question about the NRF_DRV_SPI_FLAG_REPEATED_XFER flag.it's mean the PPI trigger once read action,the spi will read one byte data or 255 byte data?When it finishes reading 255 bytes,it will auto read next 255 bytes or I need to use the read funtion again?

  • Hi again.

    When you want to transmit you can either start the transmitt transaction by:

    1) Manually with PPI

    2) By using the spi-functions.

    If you want to send many transactions with data you have to wait for the event that tells you that the "current transaction" you are sending is finished, before you start the next transaction.

    Best regards,

    Andreas

Related