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

two spi parallel

i am using nrf52832 in sdk11. I am interfacing motion sensor and spi flash memory. Both motion sensor and spi flash shares spi lines and having different chip select pin.

both working good individually but when i combine them i give spi instance 0 to one device and spi instance 1 to another device. The device having spi instance 0 works fine but data from other device is not coming. i have made spi0 and spi1 enabled in sdk_config.h and also tried with chip select with gpio, but nothing works...

Parents
  • If they share the same SPI lines then, surely, they must be sharing the same SPI instance ?

  • i don't know, but i tried to give them same spi instance "0",but only one device works...

  • So what testing / investigation / debugging have you done to find what's going on?

    Are you getting any error codes?

    Are the SPI lines behaving correctly?

  • yes i debug it but nothing found.

    i am not getting error codes.

    i didn't check the spi lines....but they are connected correctly..

    are you sure both should have same instances?

    i have given both spi instance id as "0"

    i am giving initialization fuction for both:

    static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(flash_SPI_INSTANCE_ID);
    uint32_t flash_init(void)
    {

    const nrf_drv_spi_config_t flash_config = { \
    .sck_pin = flash_SCK_PIN,
    .mosi_pin = flash_MOSI_PIN,
    .miso_pin = flash_MISO_PIN,
    .ss_pin = flash_CS_PIN,
    .irq_priority = APP_IRQ_PRIORITY_HIGH,
    .orc = 0xFF,
    .frequency = NRF_DRV_SPI_FREQ_1M,
    .mode = NRF_DRV_SPI_MODE_0,
    .bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST,
    };

    return nrf_drv_spi_init(&spi, &flash_config,spi_event_handler);
    }

    uint32_t nrf_drv_mpu_init(void)
    {

    const nrf_drv_spi_config_t spi_mpu_config = { \
    .sck_pin = MPU_SPI_SCL_PIN,
    .mosi_pin = MPU_SPI_MOSI_PIN,
    .miso_pin = MPU_SPI_MISO_PIN,
    .ss_pin = MPU_SPI_CS_PIN,
    .irq_priority = APP_IRQ_PRIORITY_HIGH,
    .orc = 0xFF,
    .frequency = NRF_DRV_SPI_FREQ_1M,
    .mode = NRF_DRV_SPI_MODE_0,
    .bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST,
    };

    return nrf_drv_spi_init(&m_spi_instance, &spi_mpu_config, nrf_drv_mpu_spi_event_handler);

Reply
  • yes i debug it but nothing found.

    i am not getting error codes.

    i didn't check the spi lines....but they are connected correctly..

    are you sure both should have same instances?

    i have given both spi instance id as "0"

    i am giving initialization fuction for both:

    static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(flash_SPI_INSTANCE_ID);
    uint32_t flash_init(void)
    {

    const nrf_drv_spi_config_t flash_config = { \
    .sck_pin = flash_SCK_PIN,
    .mosi_pin = flash_MOSI_PIN,
    .miso_pin = flash_MISO_PIN,
    .ss_pin = flash_CS_PIN,
    .irq_priority = APP_IRQ_PRIORITY_HIGH,
    .orc = 0xFF,
    .frequency = NRF_DRV_SPI_FREQ_1M,
    .mode = NRF_DRV_SPI_MODE_0,
    .bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST,
    };

    return nrf_drv_spi_init(&spi, &flash_config,spi_event_handler);
    }

    uint32_t nrf_drv_mpu_init(void)
    {

    const nrf_drv_spi_config_t spi_mpu_config = { \
    .sck_pin = MPU_SPI_SCL_PIN,
    .mosi_pin = MPU_SPI_MOSI_PIN,
    .miso_pin = MPU_SPI_MISO_PIN,
    .ss_pin = MPU_SPI_CS_PIN,
    .irq_priority = APP_IRQ_PRIORITY_HIGH,
    .orc = 0xFF,
    .frequency = NRF_DRV_SPI_FREQ_1M,
    .mode = NRF_DRV_SPI_MODE_0,
    .bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST,
    };

    return nrf_drv_spi_init(&m_spi_instance, &spi_mpu_config, nrf_drv_mpu_spi_event_handler);

Children
  • i didn't check the spi lines....but they are connected correctly..

    You need to check what is actually happening on those lines; ie, the electrical activity.

    • Are you getting a clock?
    • Are the Chip Selects working correctly?
    • etc, etc, ...
    are you sure both should have same instances?

    No.

    The Nordic documentation is rather poor here - I can' see any clear statement of what an "instance" actually represents.

    You could trawl through the code to see if it ends up representing one particular hardware peripheral ...

    How to properly post source code:

  • sorry awneil,

    i am attaching the files where you can see the spi instances.

     /* 
      * This example is not extensively tested and only 
      * meant as a simple explanation and for inspiration. 
      * NO WARRANTY of ANY KIND is provided. 
      */
    
    #include <stdio.h>
    #include "boards.h"
    #include "app_uart.h"
    #include "app_error.h"
    #include "nrf_delay.h"
    #include "app_mpu_20648.h"
    #include "memory.h"
    #include "nrf_gpio.h"
    #include "app_util_platform.h"
    #include "app_error.h"
    #include <string.h>
    #define NRF_LOG_MODULE_NAME "APP"
    #include "nrf_log.h"
    //#include "nrf_log_ctrl.h"
    #include "memory.h"
    #include "SEGGER_RTT.h"
    
    
    
    
    /*UART buffer size. */
    #define UART_TX_BUF_SIZE 256
    #define UART_RX_BUF_SIZE 1
    uint8_t data_val[256];
    
    /**
     * @brief UART events handler.
     */
    static void uart_events_handler(app_uart_evt_t * p_event)
    {
        switch (p_event->evt_type)
        {
            case APP_UART_COMMUNICATION_ERROR:
                APP_ERROR_HANDLER(p_event->data.error_communication);
                break;
    
            case APP_UART_FIFO_ERROR:
                APP_ERROR_HANDLER(p_event->data.error_code);
                break;
    
            default:
                break;
        }
    }
    
    
    /**
     * @brief UART initialization.
     * Just the usual way. Nothing special here
     */
    static void uart_config(void)
    {
        uint32_t                     err_code;
        const app_uart_comm_params_t comm_params =
        {
            RX_PIN_NUMBER,
            TX_PIN_NUMBER,
            RTS_PIN_NUMBER,
            CTS_PIN_NUMBER,
            APP_UART_FLOW_CONTROL_DISABLED,
            false,
            UART_BAUDRATE_BAUDRATE_Baud115200
        };
    
        APP_UART_FIFO_INIT(&comm_params,
                           UART_RX_BUF_SIZE,
                           UART_TX_BUF_SIZE,
                           uart_events_handler,
                           APP_IRQ_PRIORITY_LOW,
                           err_code);
    
        APP_ERROR_CHECK(err_code);
    }
    
    
    
    void mpu_setup(void)
    {
        ret_code_t ret_code;
        // Initiate MPU driver
        ret_code = mpu_init();
        APP_ERROR_CHECK(ret_code); // Check for errors in return value
        
        // Setup and configure the MPU with intial values
        mpu_config_t p_mpu_config = MPU_DEFAULT_CONFIG(); // Load default values
        p_mpu_config.smplrt_div = 19;   // Change sampelrate. Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV). 19 gives a sample rate of 50Hz
        p_mpu_config.accel_config.afs_sel = AFS_2G; // Set accelerometer full scale range to 2G
        ret_code = mpu_config(&p_mpu_config); // Configure the MPU with above values
        APP_ERROR_CHECK(ret_code); // Check for errors in return value 
    }
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {    
        uint32_t err_code;
    	/*LEDS_CONFIGURE(LEDS_MASK);
    	LEDS_OFF(LEDS_MASK);
        uart_config();*/
       // printf("\033[2J\033[;HMPU simple example. Compiled @ %s\r\n", __TIME__);
      mpu_setup();
    	flash_init();  
      accel_values_t acc_values;
    	gyro_values_t gyro_values;
        uint32_t sample_number = 0;
        while(1)
        {
            // Read accelerometer sensor values
          err_code = mpu_read_accel(&acc_values);
            APP_ERROR_CHECK(err_code);
    			err_code = mpu_read_gyro(&gyro_values);
            APP_ERROR_CHECK(err_code);
    			nrf_delay_ms(5000);
    			FLASH_Print_ID();
    		// Clear terminal and print values
      //  SEGGER_RTT_printf(0,"\033[3;1HSample # %d\r\nX: %06d\r\nY: %06d\r\nZ: %06d\r\n gyrox:%06d\r\n gyroy=%d\r\n gyroz=%d\r\n", ++sample_number, acc_values.x, acc_values.y, acc_values.z,gyro_values.x,gyro_values.y,gyro_values.z);
    			nrf_gpio_pin_toggle(LED_1);
            nrf_delay_ms(250);
        }
    }
    
    /** @} */
    #include "memory.h"
    #include "nrf_delay.h"
    #include "SEGGER_RTT.h"
    #include "nrf_drv_spi.h"
    #include "app_util_platform.h"
    
    #define NRF_LOG_MODULE_NAME "FLASH"
    
    #define CMD_PAGE_PROGRAM        ((uint8_t)0x02)
    #define CMD_WRITE_ENABLE        ((uint8_t)0x06)
    #define CMD_READ_DATA           ((uint8_t)0x03)
    #define CMD_READ_ID             ((uint8_t)0x9F)
    #define CMD_READ_STATUS_REG     ((uint8_t)0x05)
    
    #define flash_SPI_INSTANCE_ID   0
    #define QUEUE_LENGTH     10
    #define flash_SCK_PIN 4
    #define flash_MOSI_PIN 27
    #define flash_MISO_PIN 26
    #define flash_CS_PIN 18
    
    //will return either a 1 or 0 if the bit is enabled
    #define CHECK_BIT(var,pos) (((var)>>(pos)) & 1)
    void spi_event_handler(nrf_drv_spi_evt_t const * p_event)
    {
       
       // NRF_LOG_INFO("Transfer completed.\r\n");
      //  if (m_rx_buf[0] != 0)
        {
      //      NRF_LOG_INFO(" Received: \r\n");
           // NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
        }
    }
    static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(flash_SPI_INSTANCE_ID);
    uint32_t flash_init(void)
    {
        
        const nrf_drv_spi_config_t flash_config = {                                                            \
            .sck_pin      = flash_SCK_PIN, 
            .mosi_pin     = flash_MOSI_PIN,
            .miso_pin     = flash_MISO_PIN,
            .ss_pin       = flash_CS_PIN,
            .irq_priority = APP_IRQ_PRIORITY_HIGH, 
            .orc          = 0xFF,                                    
            .frequency    = NRF_DRV_SPI_FREQ_1M,                     
            .mode         = NRF_DRV_SPI_MODE_0,                      
            .bit_order    = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST,         
        };
        
        return nrf_drv_spi_init(&spi, &flash_config,spi_event_handler);  
    }
    
    static uint8_t cmd[1] = { 0 };
    
    static uint8_t tx4[4];
    
    static uint8_t rx2[2];
    static uint8_t rx4[4];
    static uint8_t rx5[5];
    static uint8_t rx8[8];
    static uint8_t rx256[256];
    
    static uint8_t rxHalf[4+128];
    static uint8_t txHalf[4+128];
    
    static uint8_t rx20[16+4];
    uint8_t err_code;
    
    #define APP_IRQ_PRIORITY_LOW 3  //overrides definition elsewhere
    
    void FLASH_Print_ID( void )
    {
        cmd[0] = CMD_READ_ID; //Get JEDEC ID
        memset(rx4, 0, sizeof(rx4));
       APP_ERROR_CHECK( nrf_drv_spi_transfer(&spi, cmd, sizeof(cmd), rx4, sizeof(rx4))); // rx + tx
    		nrf_delay_ms(100);
        SEGGER_RTT_printf(0, "MemID: %x Type: %x CAP: %x\r\n", rx4[1], rx4[2], rx4[3]); 
    }
    
    bool FLASH_Is_Busy( void ) 
    {
        memset(rx2, 0, sizeof(rx2));
        cmd[0] = CMD_READ_STATUS_REG;
        nrf_drv_spi_transfer(&spi, cmd, sizeof(cmd), rx2, sizeof(rx2));
    		nrf_delay_ms(200);
    	
        //bool retval = false;
        
        if ( CHECK_BIT(rx2[1],0) == 1 ) return true;
        //{
        //    retval = true;
            //NRF_LOG_DEBUG("FLASH_Is_Busy!\r\n"); 
        //} 
        return false;
    }
    
    uint8_t FLASH_Read_Status( void )
    {
        memset(rx2, 0, sizeof(rx2));
        cmd[0] = CMD_READ_STATUS_REG;
        nrf_drv_spi_transfer(&spi, cmd, sizeof(cmd), rx2, sizeof(rx2));
        nrf_delay_ms(200);
        /* S0; 1 = busy
           S1; Write Enable Latch (WEL) is a read only bit in the status register 
           that is set to 1 after executing a Write Enable Instruction. 
           The WEL status bit is cleared to 0 when the device is write disabled
        */
        if ( CHECK_BIT(rx2[1],0) ) {  
            //NRF_LOG_DEBUG("SR: Busy\r\n")
    				SEGGER_RTT_printf(0, "busy\n");
        } else {
            //NRF_LOG_DEBUG("SR: Ready\r\n")
    				SEGGER_RTT_printf(0, "ready\n");
        };
       
        if ( CHECK_BIT(rx2[1],1) ) {
            //NRF_LOG_DEBUG("SR: WEL\r\n")
    				SEGGER_RTT_printf(0, "wel\n");
        } else {
            //NRF_LOG_DEBUG("SR: NoWEL\r\n")
    				SEGGER_RTT_printf(0, "nowel\n");
        };
        return rx2[1];
    }
    
    bool FLASH_Is_Write_Enabled( void ) 
    {
        memset(rx2, 0, sizeof(rx2));
        cmd[0] = CMD_READ_STATUS_REG;
        nrf_drv_spi_transfer(&spi, cmd, sizeof(cmd), rx2, sizeof(rx2));
    		nrf_delay_ms(100);
    	
        //bool retval = true;
        
        //S1 == 1 Write Enable Latch (WEL) is a read only bit in the status register 
        if ( CHECK_BIT(rx2[1],1) != 1) return false;
        //{
            
        //NRF_LOG_DEBUG("FLASH_Is_Write_Enabled: False\r\n"); 
        //}
        return true;
    }
    
    bool FLASH_Set_Write_Enable( void )
    {
      bool enabled = false;
      cmd[0] = CMD_WRITE_ENABLE;
      nrf_drv_spi_transfer(&spi, cmd, sizeof(cmd), NULL, 0);
    	nrf_delay_ms(100);
    	
      if( FLASH_Is_Write_Enabled() ) {
        enabled = true;
      } else {
        enabled = false;
        //NRF_LOG_DEBUG("FLASH_Set_Write_Enable Fail\r\n");
      };
        
      return enabled;
    }
    
    uint8_t * FLASH_Page_Read( uint16_t pageN )
    {
      
      memset(   tx4, 0, sizeof(   tx4));
      memset( rx256, 0, sizeof( rx256));
      memset(rxHalf, 0, sizeof(rxHalf));
      
      if ( pageN >  8192 ) { //memory has 4095 pages 
          //NRF_LOG_DEBUG("FLASH_Page_Read: Out of bounds!\r\n")
          return rx256;
      };
      
      int address = page_to_address( pageN );
      
      //read the first 1/2
      tx4[0] = CMD_READ_DATA;
      tx4[1] = (address >> 16) & 0xFF;
      tx4[2] = (address >>  8) & 0xFF;
      tx4[3] =  address        & 0xFF;
      
      uint16_t i = 0;
      
      nrf_drv_spi_transfer(&spi, tx4, sizeof(tx4), rxHalf, sizeof(rxHalf) + sizeof(tx4)); // rx + tx 
    	nrf_delay_ms(200);
      for(i =   0; i < 128; i++) { rx256[i] = rxHalf[i+4]; };  
      
      tx4[3] = 128;
      memset(rxHalf, 0, sizeof(rxHalf));
      
      nrf_drv_spi_transfer(&spi, tx4, sizeof(tx4), rxHalf, sizeof(rxHalf) + sizeof(tx4)); //rx + tx
    	nrf_delay_ms(200);
      for(i = 128; i < 256; i++) { rx256[i] = rxHalf[(i-128)+4]; };  
      
      //NRF_LOG_HEXDUMP_DEBUG((uint8_t *)rx256, 256);
      
      //SEGGER_RTT_WriteString(0, "Reading now!");  
    
      for(i = 0;   i <  16; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 16;  i <  32; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 32;  i <  48; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 48;  i <  64; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      
      nrf_delay_ms(100);
      
      for(i = 64;  i <  80; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 80;  i <  96; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 96;  i < 112; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 112; i < 128; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      
      nrf_delay_ms(100);
    
      for(i = 128; i < 144; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 144; i < 160; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 160; i < 176; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 176; i < 192; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      
      nrf_delay_ms(100);
      
      for(i = 192; i < 208; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 208; i < 224; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 224; i < 240; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 240; i < 256; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
    
      /*
      SEGGER_RTT_printf(0, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", \
              rx256[i], rx256[i],rx256[i],rx256[i],rx256[i],rx256[i],rx256[i],rx256[i])
        
      for(i = 0; i < 256; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); };  
      
      SEGGER_RTT_WriteString(0, "\n");
      */ 
      return rx256;
    }
    
    void FLASH_Erase( void )
    {
      if( !FLASH_Set_Write_Enable() ) {
          //NRF_LOG_DEBUG("Erase: Write not enabled\r\n");
      }
      
      if ( FLASH_Is_Busy() ) {
          //NRF_LOG_DEBUG("Erase: FLASH is busy\r\n");
      }
      
      //NRF_LOG_DEBUG("Erase: Erasing Flash\r\n");
      
      cmd[0] = 0xC7;
      nrf_drv_spi_transfer(&spi, cmd, sizeof(cmd), NULL, 0); 
    	nrf_delay_ms(200);
      //wait for some
      while ( FLASH_Is_Busy() ) {
          nrf_delay_ms(1500);
          //NRF_LOG_DEBUG("Erase: FLASH is still busy\r\n");
      }
    }
    
    void FLASH_Reset( void )
    {
        cmd[0] = 0xF0;
        nrf_drv_spi_transfer(&spi, cmd, sizeof(cmd), NULL, 0); 
    		nrf_delay_ms(200);
    }
    
    int address_to_page(int addr) 
    {
      return(addr >> 8);
    }
    
    int page_to_address(int pn) 
    {
      return(pn << 8);
    }
    
    uint16_t FLASH_Get_First_Available_Location( void )
    {
       //this assumes that data were written contiguously
       uint16_t ds;       
       for(ds = 0; ds < 8192; ds++)
       {
           //NRF_LOG_DEBUG("Testing page %d\r\n", ds);
           
           if( FLASH_Page_Is_Empty( ds ) )
           {
              //NRF_LOG_DEBUG("Page %d is empty.\r\n", ds);
              return ds;
           } else {
              //keep searching 
              //NRF_LOG_DEBUG("Page %d is full.\r\n", ds);
           };
       };
       //should never really get here 
       //NRF_LOG_DEBUG("No memory available!\r\n", ds);
       return 8192;
    }
    
    bool FLASH_Page_Is_Empty( uint16_t pageN )
    {
      if ( pageN > 8192 - 1 ) { //memory has 16384 pages 
          //NRF_LOG_DEBUG("FLASH_PE: Out of bounds!\r\n")
          return false; //err on the side of safety
      };
      
      memset(tx4, 0, sizeof(tx4));
      memset(rx8, 0, sizeof(rx8));
      
      int address = page_to_address( pageN );
      
      tx4[0] = CMD_READ_DATA;
      tx4[1] = (address >> 16) & 0xFF;
      tx4[2] = (address >>  8) & 0xFF;
      tx4[3] =  address        & 0xFF;
      
      //NRF_LOG_HEXDUMP_DEBUG((uint8_t *)send4, 4);
      nrf_drv_spi_transfer(&spi, tx4, sizeof(tx4), rx8, sizeof(rx8));
      nrf_delay_ms(200);     
    	
      uint16_t check = rx8[4] + rx8[5] + rx8[6] + rx8[7];
      //empty = 255, so 255+255+255+255 = 1020
      //NRF_LOG_INFO("FLASH_PE Page:%d contains:%d\r\n", pageN, check);
      //NRF_LOG_HEXDUMP_DEBUG((uint8_t *)rx8, 8);
      
      if ( check == 1020 ) {
        //NRF_LOG_DEBUG("FLASH_PE: Page:%d is empty.\r\n", pageN);
        return true;
      } else {
        //NRF_LOG_DEBUG("FLASH_PE: Page:%d contains:%d\r\n", pageN, check);
        return false;
      }
    }
    
    int FLASH_Page_Write( uint16_t pageN, uint8_t *wp )
    {
      //memory has 0-4095 pages, and each page has length 256    
      if ( pageN > 8192 - 1 ) {
          //NRF_LOG_DEBUG("FLASH_Page_Write: Out of bounds!\r\n")
          return 1;
      };
        
      if ( !FLASH_Set_Write_Enable() ) {
          //NRF_LOG_DEBUG("FLASH_Page_Write: Write not enabled!\r\n")
          return 2;
      };
      
      if ( FLASH_Is_Busy() ) {
          //NRF_LOG_DEBUG("FLASH_Page_Write: Busy!\r\n")
          return 3;
      };
      
      if ( FLASH_Page_Is_Empty( pageN) == false ) {
          //NRF_LOG_DEBUG("FLASH_Page_Write: Page already contains data!\r\n")
          return 4;
      }
     
      //NRF_LOG_DEBUG("Write looking good\r\n");
     
      //the command and address
      int address = page_to_address( pageN );
      
      memset(txHalf, 0, sizeof(txHalf));
      
      txHalf[0] = CMD_PAGE_PROGRAM;
      txHalf[1] = (address >> 16) & 0xFF;
      txHalf[2] = (address >> 8)  & 0xFF;
      txHalf[3] =  address        & 0xFF;
    
      uint16_t i = 0;
      
      //write the first 128 bytes
      for( i = 4; i < (128+4); i++ ) { txHalf[i] = wp[i-4]; };
      nrf_drv_spi_transfer(&spi, txHalf, sizeof(txHalf), NULL, 0);
      //wait for at most 200 ms to make sure write completes
      for( i = 0; i < 10; i++ ) {
          nrf_delay_ms(20); 
          if ( FLASH_Is_Busy() ) {
              //wait
          } else {
              break;   
          }
      }
    
      //wait for at most 200 ms to make sure we are good for next write
      for( i = 0; i < 10; i++ ) {
          nrf_delay_ms(20); 
          if ( FLASH_Set_Write_Enable() ) {
              break;
          } else {
              //NRF_LOG_DEBUG("Erase: Not able to write\r\n");
          }
      }
      
      //write the next 128 bytes
      txHalf[3] = 128;
      for( i = 4; i < (128+4); i++ ) { txHalf[i] = wp[i-4+128]; };
      nrf_drv_spi_transfer(&spi, txHalf, sizeof(txHalf), NULL, 0);
    	nrf_delay_ms(100);
      return 0;
    }
    
    
    void FLASH_WriteCustom(uint8_t value)
    {
    		FLASH_Set_Write_Enable();
    		memset(rx5, 0, sizeof(rx5));
    	
    		rx5[0] = CMD_PAGE_PROGRAM;
    		rx5[1] = 0x00;
    		rx5[2] = 0x00;
    		rx5[3] = 0x01;
    		rx5[4] = value;
    		nrf_drv_spi_transfer(&spi, rx5, sizeof(rx5), NULL, 0);
    		nrf_delay_ms(100);
    }
    
    void FLASH_CustomRead()
    {
    		FLASH_Set_Write_Enable();
    		memset(tx4, 0, sizeof(rx4));
    		memset(rx2, 0, sizeof(rx2));
    	
    		rx4[0] = CMD_PAGE_PROGRAM;
    		rx4[1] = 0x00;
    		rx4[2] = 0x00;
    		rx4[3] = 0x01;
    	
    		nrf_drv_spi_transfer(&spi, tx4, sizeof(tx4), cmd, sizeof(rx2));
    		SEGGER_RTT_printf(0, "%d %d\n", *cmd, *(cmd+1));
    }
    
    
     /*
      * The library is not extensively tested and only
      * meant as a simple explanation and for inspiration.
      * NO WARRANTY of ANY KIND is provided.
      */
    
    #include <stdbool.h>
    #include <stdint.h>
    #include <string.h>
    #include "nrf_drv_spi.h"
    #include "nrf_drv_mpu.h"
    #include "app_util_platform.h"
    #include "nrf_gpio.h"
    #include "SEGGER_RTT.h"
    #define SPI_INSTANCE_ID   0
    
    #if defined(MPU9150)
    #error "MPU9150 does not support SPI"
    #endif
    
    /* Pins to connect MPU. Pinout is different for nRF51 DK and nRF52 DK
     * and therefore I have added a conditional statement defining different pins
     * for each board. This is only for my own convenience and might be subject to changes as I devleop. 
     */
    #if defined(BOARD_PCA10040)
    
    
    
    
    #define MPU_SPI_MISO_PIN    26 // MPU SDO. 'AD0' on MPU breakout board silk screen
    #define MPU_SPI_MOSI_PIN    27// MPU SDI. 'SDA' on MPU breakout board silk screen
    
    #define MPU_SPI_SCL_PIN     4  // MPU SCLK. 'SCL' on MPU breakout board silk screen
    #define MPU_SPI_CS_PIN      5 // MPU nCS. 'NCS' on MPU breakout board silk screen1/
    #else // If PCA10028
    #define MPU_SPI_MISO_PIN    3 // MPU SDO. 'AD0' on MPU breakout board silk screen
    #define MPU_SPI_MOSI_PIN    2  // MPU SDI. 'SDA' on MPU breakout board silk screen
    #define MPU_SPI_SCL_PIN     1  // MPU SCLK. 'SCL' on MPU breakout board silk screen
    #define MPU_SPI_CS_PIN      4 // MPU nCS. 'NCS' on MPU breakout board silk screen
    #endif
    
    
    #define MPU_SPI_BUFFER_SIZE     14 // 14 byte buffers will suffice to read acceleromter, gyroscope and temperature data in one transmission.
    #define MPU_SPI_WRITE_BIT       0x00
    #define MPU_SPI_READ_BIT        0x80
    #define MPU_SPI_TIMEOUT         5000 
    
    
    static const nrf_drv_spi_t m_spi_instance = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE_ID);
    volatile static bool spi_tx_done = false;
    
    
    uint8_t spi_tx_buffer[MPU_SPI_BUFFER_SIZE];
    uint8_t spi_rx_buffer[MPU_SPI_BUFFER_SIZE];
    
    
    void nrf_drv_mpu_spi_event_handler(const nrf_drv_spi_evt_t *evt)
    {
        if(evt->type == NRF_DRV_SPI_EVENT_DONE)
        {
            spi_tx_done = true;
        }
        else
        {
            // Something is wrong
        }
    }
    
    
    
    /**
     * @brief SPI initialization.
     * Just the usual way. Nothing special here
     */
    uint32_t nrf_drv_mpu_init(void)
    {
        
        const nrf_drv_spi_config_t spi_mpu_config = {                                                            \
            .sck_pin      = MPU_SPI_SCL_PIN, 
            .mosi_pin     = MPU_SPI_MOSI_PIN,
            .miso_pin     = MPU_SPI_MISO_PIN,
            .ss_pin       = MPU_SPI_CS_PIN,
            .irq_priority = APP_IRQ_PRIORITY_HIGH, 
            .orc          = 0xFF,                                    
            .frequency    = NRF_DRV_SPI_FREQ_1M,                     
            .mode         = NRF_DRV_SPI_MODE_0,                      
            .bit_order    = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST,         
        };
        
        return nrf_drv_spi_init(&m_spi_instance, &spi_mpu_config, nrf_drv_mpu_spi_event_handler);  
    }
    
    
    
    /**@brief Function to merge a register and a buffer of data
     */
    static void merge_register_and_data(uint8_t * new_buffer, uint8_t reg, uint8_t * p_data, uint32_t length)
    {
        new_buffer[0] = reg;
        memcpy((new_buffer + 1), p_data, length);
    }
    
    
    /**@brief Function to write a series of bytes. The function merges 
     * the register and the data.
     */
    uint32_t nrf_drv_mpu_write_registers(uint8_t reg, uint8_t * p_data, uint32_t length)
    {
        uint32_t err_code;
        
        if(length > MPU_SPI_BUFFER_SIZE - 1) // Must be space for register byte in buffer
        {
            return NRF_ERROR_DATA_SIZE;
        }
        
        uint32_t timeout = MPU_SPI_TIMEOUT;
        // Add write bit to register. 
        reg = reg | MPU_SPI_WRITE_BIT;
        
        merge_register_and_data(spi_tx_buffer, reg, p_data, length + 1);
        
        err_code = nrf_drv_spi_transfer(&m_spi_instance, spi_tx_buffer, length + 1, NULL, 0);
        if(err_code != NRF_SUCCESS) return err_code;
    
    
        while((!spi_tx_done) && --timeout);
        if(!timeout) return NRF_ERROR_TIMEOUT;
        spi_tx_done = false;
    
        return err_code;
    }
    
    uint32_t nrf_drv_mpu_write_single_register(uint8_t reg, uint8_t data)
    {
        uint32_t err_code;
        uint32_t timeout = MPU_SPI_TIMEOUT;
    
        uint8_t packet[2] = {reg, data};
    
        // Add write bit to register. 
        reg = reg | MPU_SPI_WRITE_BIT;
        
        err_code = nrf_drv_spi_transfer(&m_spi_instance, packet, 2, NULL, 0);
        if(err_code != NRF_SUCCESS) return err_code;
    
        while((!spi_tx_done) && --timeout);
        if(!timeout) return NRF_ERROR_TIMEOUT;
    
        spi_tx_done = false;
    
        return err_code;
    }
    
    
    uint32_t nrf_drv_mpu_read_registers(uint8_t reg, uint8_t * p_data, uint32_t length)
    {
        uint32_t err_code;
        uint32_t timeout = MPU_SPI_TIMEOUT;
        
        // Add read bit to register. 
        reg = reg | MPU_SPI_READ_BIT;
    	
        // Read data over SPI and store incomming data in spi_rx_buffer
        err_code = nrf_drv_spi_transfer(&m_spi_instance, &reg, 1, spi_rx_buffer, length + 1); // Length + 1 because register byte has to be clocked out before MPU returns data of length 'length'
        if(err_code != NRF_SUCCESS) return err_code;
    
        while((!spi_tx_done) && --timeout);
        if(!timeout) return NRF_ERROR_TIMEOUT;
        spi_tx_done = false;
    	
    	// Copy data in spi_rx_buffer over to p_data
    	memcpy(p_data, &spi_rx_buffer[1], length);
    
        return NRF_SUCCESS;
    }
    
    
    
    /**
      @}
    */
    

  • Hi

    • Only one SPI instance should be used for the bus.
    •  As already mentioned, we should ensure that your HW is setup correctly, before debugging your code. Could you provide a Schematic of the design? 
    • Can you measure if there is any activity on the lines during the SPI communication?
    • Is Chip select set properly?

    Jared 

  • i am using only one spi instance

    hardware is setup correct, we had confirmed with nordic...

    yes there is activity on spi lines...

    will you check the code?

    i am attaching the revised code..

    #include "memory.h"
    #include "nrf_delay.h"
    #include "SEGGER_RTT.h"
    #include "nrf_drv_spi.h"
    #include "app_util_platform.h"
    #include "nrf_gpio.h"
    
    #define NRF_LOG_MODULE_NAME "FLASH"
    
    #define CMD_PAGE_PROGRAM        ((uint8_t)0x02)
    #define CMD_WRITE_ENABLE        ((uint8_t)0x06)
    #define CMD_READ_DATA           ((uint8_t)0x03)
    #define CMD_READ_ID             ((uint8_t)0x9F)
    #define CMD_READ_STATUS_REG     ((uint8_t)0x05)
    
    #define flash_SPI_INSTANCE_ID   0
    #define QUEUE_LENGTH     10
    #define flash_SCK_PIN 4
    #define flash_MOSI_PIN 27
    #define flash_MISO_PIN 26
    #define flash_CS_PIN 18
    #define flash_cs 18
    
    //will return either a 1 or 0 if the bit is enabled
    #define CHECK_BIT(var,pos) (((var)>>(pos)) & 1)
    void spi_event_handler(nrf_drv_spi_evt_t const * p_event)
    {
       
       // NRF_LOG_INFO("Transfer completed.\r\n");
      //  if (m_rx_buf[0] != 0)
        {
      //      NRF_LOG_INFO(" Received: \r\n");
           // NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
        }
    }
    static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(flash_SPI_INSTANCE_ID);
    uint32_t flash_init(void)
    {
        
        const nrf_drv_spi_config_t flash_config = {                                                            \
            .sck_pin      = flash_SCK_PIN, 
            .mosi_pin     = flash_MOSI_PIN,
            .miso_pin     = flash_MISO_PIN,
            .ss_pin       = NRF_DRV_SPI_PIN_NOT_USED,//flash_CS_PIN,
            .irq_priority = APP_IRQ_PRIORITY_HIGH, 
            .orc          = 0xFF,                                    
            .frequency    = NRF_DRV_SPI_FREQ_1M,                     
            .mode         = NRF_DRV_SPI_MODE_0,                      
            .bit_order    = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST,         
        };
        
        return nrf_drv_spi_init(&spi, &flash_config,spi_event_handler);  
    }
    
    static uint8_t cmd[1] = { 0 };
    
    static uint8_t tx4[4];
    
    static uint8_t rx2[2];
    static uint8_t rx4[4];
    static uint8_t rx5[5];
    static uint8_t rx8[8];
    static uint8_t rx256[256];
    
    static uint8_t rxHalf[4+128];
    static uint8_t txHalf[4+128];
    
    static uint8_t rx20[16+4];
    uint8_t err_code;
    
    
    #define APP_IRQ_PRIORITY_LOW 3  //overrides definition elsewhere
    
    void FLASH_Print_ID( void )
    { nrf_gpio_cfg_output(flash_cs);
    	nrf_gpio_pin_clear(flash_cs);
        cmd[0] = CMD_READ_ID; //Get JEDEC ID
        memset(rx4, 0, sizeof(rx4));
       APP_ERROR_CHECK( nrf_drv_spi_transfer(&spi, cmd, sizeof(cmd), rx4, sizeof(rx4))); // rx + tx
    		nrf_delay_ms(100);
        SEGGER_RTT_printf(0, "MemID: %x Type: %x CAP: %x\r\n", rx4[1], rx4[2], rx4[3]); 
    	nrf_gpio_pin_set(flash_cs);
    }
    
    bool FLASH_Is_Busy( void ) 
    {
        memset(rx2, 0, sizeof(rx2));
        cmd[0] = CMD_READ_STATUS_REG;
        nrf_drv_spi_transfer(&spi, cmd, sizeof(cmd), rx2, sizeof(rx2));
    		nrf_delay_ms(200);
    	
        //bool retval = false;
        
        if ( CHECK_BIT(rx2[1],0) == 1 ) return true;
        //{
        //    retval = true;
            //NRF_LOG_DEBUG("FLASH_Is_Busy!\r\n"); 
        //} 
        return false;
    }
    
    uint8_t FLASH_Read_Status( void )
    {
        memset(rx2, 0, sizeof(rx2));
        cmd[0] = CMD_READ_STATUS_REG;
        nrf_drv_spi_transfer(&spi, cmd, sizeof(cmd), rx2, sizeof(rx2));
        nrf_delay_ms(200);
        /* S0; 1 = busy
           S1; Write Enable Latch (WEL) is a read only bit in the status register 
           that is set to 1 after executing a Write Enable Instruction. 
           The WEL status bit is cleared to 0 when the device is write disabled
        */
        if ( CHECK_BIT(rx2[1],0) ) {  
            //NRF_LOG_DEBUG("SR: Busy\r\n")
    				SEGGER_RTT_printf(0, "busy\n");
        } else {
            //NRF_LOG_DEBUG("SR: Ready\r\n")
    				SEGGER_RTT_printf(0, "ready\n");
        };
       
        if ( CHECK_BIT(rx2[1],1) ) {
            //NRF_LOG_DEBUG("SR: WEL\r\n")
    				SEGGER_RTT_printf(0, "wel\n");
        } else {
            //NRF_LOG_DEBUG("SR: NoWEL\r\n")
    				SEGGER_RTT_printf(0, "nowel\n");
        };
        return rx2[1];
    }
    
    bool FLASH_Is_Write_Enabled( void ) 
    {
        memset(rx2, 0, sizeof(rx2));
        cmd[0] = CMD_READ_STATUS_REG;
        nrf_drv_spi_transfer(&spi, cmd, sizeof(cmd), rx2, sizeof(rx2));
    		nrf_delay_ms(100);
    	
        //bool retval = true;
        
        //S1 == 1 Write Enable Latch (WEL) is a read only bit in the status register 
        if ( CHECK_BIT(rx2[1],1) != 1) return false;
        //{
            
        //NRF_LOG_DEBUG("FLASH_Is_Write_Enabled: False\r\n"); 
        //}
        return true;
    }
    
    bool FLASH_Set_Write_Enable( void )
    {
      bool enabled = false;
      cmd[0] = CMD_WRITE_ENABLE;
      nrf_drv_spi_transfer(&spi, cmd, sizeof(cmd), NULL, 0);
    	nrf_delay_ms(100);
    	
      if( FLASH_Is_Write_Enabled() ) {
        enabled = true;
      } else {
        enabled = false;
        //NRF_LOG_DEBUG("FLASH_Set_Write_Enable Fail\r\n");
      };
        
      return enabled;
    }
    
    uint8_t * FLASH_Page_Read( uint16_t pageN )
    {
      
      memset(   tx4, 0, sizeof(   tx4));
      memset( rx256, 0, sizeof( rx256));
      memset(rxHalf, 0, sizeof(rxHalf));
      
      if ( pageN >  8192 ) { //memory has 4095 pages 
          //NRF_LOG_DEBUG("FLASH_Page_Read: Out of bounds!\r\n")
          return rx256;
      };
      
      int address = page_to_address( pageN );
      
      //read the first 1/2
      tx4[0] = CMD_READ_DATA;
      tx4[1] = (address >> 16) & 0xFF;
      tx4[2] = (address >>  8) & 0xFF;
      tx4[3] =  address        & 0xFF;
      
      uint16_t i = 0;
      
      nrf_drv_spi_transfer(&spi, tx4, sizeof(tx4), rxHalf, sizeof(rxHalf) + sizeof(tx4)); // rx + tx 
    	nrf_delay_ms(200);
      for(i =   0; i < 128; i++) { rx256[i] = rxHalf[i+4]; };  
      
      tx4[3] = 128;
      memset(rxHalf, 0, sizeof(rxHalf));
      
      nrf_drv_spi_transfer(&spi, tx4, sizeof(tx4), rxHalf, sizeof(rxHalf) + sizeof(tx4)); //rx + tx
    	nrf_delay_ms(200);
      for(i = 128; i < 256; i++) { rx256[i] = rxHalf[(i-128)+4]; };  
      
      //NRF_LOG_HEXDUMP_DEBUG((uint8_t *)rx256, 256);
      
      //SEGGER_RTT_WriteString(0, "Reading now!");  
    
      for(i = 0;   i <  16; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 16;  i <  32; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 32;  i <  48; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 48;  i <  64; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      
      nrf_delay_ms(100);
      
      for(i = 64;  i <  80; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 80;  i <  96; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 96;  i < 112; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 112; i < 128; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      
      nrf_delay_ms(100);
    
      for(i = 128; i < 144; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 144; i < 160; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 160; i < 176; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 176; i < 192; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      
      nrf_delay_ms(100);
      
      for(i = 192; i < 208; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 208; i < 224; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 224; i < 240; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
      for(i = 240; i < 256; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); }; SEGGER_RTT_WriteString(0, "\n");
    
      /*
      SEGGER_RTT_printf(0, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", \
              rx256[i], rx256[i],rx256[i],rx256[i],rx256[i],rx256[i],rx256[i],rx256[i])
        
      for(i = 0; i < 256; i++) { SEGGER_RTT_printf(0, "%d ", rx256[i]); };  
      
      SEGGER_RTT_WriteString(0, "\n");
      */ 
      return rx256;
    }
    
    void FLASH_Erase( void )
    {
      if( !FLASH_Set_Write_Enable() ) {
          //NRF_LOG_DEBUG("Erase: Write not enabled\r\n");
      }
      
      if ( FLASH_Is_Busy() ) {
          //NRF_LOG_DEBUG("Erase: FLASH is busy\r\n");
      }
      
      //NRF_LOG_DEBUG("Erase: Erasing Flash\r\n");
      
      cmd[0] = 0xC7;
      nrf_drv_spi_transfer(&spi, cmd, sizeof(cmd), NULL, 0); 
    	nrf_delay_ms(200);
      //wait for some
      while ( FLASH_Is_Busy() ) {
          nrf_delay_ms(1500);
          //NRF_LOG_DEBUG("Erase: FLASH is still busy\r\n");
      }
    }
    
    void FLASH_Reset( void )
    {
        cmd[0] = 0xF0;
        nrf_drv_spi_transfer(&spi, cmd, sizeof(cmd), NULL, 0); 
    		nrf_delay_ms(200);
    }
    
    int address_to_page(int addr) 
    {
      return(addr >> 8);
    }
    
    int page_to_address(int pn) 
    {
      return(pn << 8);
    }
    
    uint16_t FLASH_Get_First_Available_Location( void )
    {
       //this assumes that data were written contiguously
       uint16_t ds;       
       for(ds = 0; ds < 8192; ds++)
       {
           //NRF_LOG_DEBUG("Testing page %d\r\n", ds);
           
           if( FLASH_Page_Is_Empty( ds ) )
           {
              //NRF_LOG_DEBUG("Page %d is empty.\r\n", ds);
              return ds;
           } else {
              //keep searching 
              //NRF_LOG_DEBUG("Page %d is full.\r\n", ds);
           };
       };
       //should never really get here 
       //NRF_LOG_DEBUG("No memory available!\r\n", ds);
       return 8192;
    }
    
    bool FLASH_Page_Is_Empty( uint16_t pageN )
    {
      if ( pageN > 8192 - 1 ) { //memory has 16384 pages 
          //NRF_LOG_DEBUG("FLASH_PE: Out of bounds!\r\n")
          return false; //err on the side of safety
      };
      
      memset(tx4, 0, sizeof(tx4));
      memset(rx8, 0, sizeof(rx8));
      
      int address = page_to_address( pageN );
      
      tx4[0] = CMD_READ_DATA;
      tx4[1] = (address >> 16) & 0xFF;
      tx4[2] = (address >>  8) & 0xFF;
      tx4[3] =  address        & 0xFF;
      
      //NRF_LOG_HEXDUMP_DEBUG((uint8_t *)send4, 4);
      nrf_drv_spi_transfer(&spi, tx4, sizeof(tx4), rx8, sizeof(rx8));
      nrf_delay_ms(200);     
    	
      uint16_t check = rx8[4] + rx8[5] + rx8[6] + rx8[7];
      //empty = 255, so 255+255+255+255 = 1020
      //NRF_LOG_INFO("FLASH_PE Page:%d contains:%d\r\n", pageN, check);
      //NRF_LOG_HEXDUMP_DEBUG((uint8_t *)rx8, 8);
      
      if ( check == 1020 ) {
        //NRF_LOG_DEBUG("FLASH_PE: Page:%d is empty.\r\n", pageN);
        return true;
      } else {
        //NRF_LOG_DEBUG("FLASH_PE: Page:%d contains:%d\r\n", pageN, check);
        return false;
      }
    }
    
    int FLASH_Page_Write( uint16_t pageN, uint8_t *wp )
    {
      //memory has 0-4095 pages, and each page has length 256    
      if ( pageN > 8192 - 1 ) {
          //NRF_LOG_DEBUG("FLASH_Page_Write: Out of bounds!\r\n")
          return 1;
      };
        
      if ( !FLASH_Set_Write_Enable() ) {
          //NRF_LOG_DEBUG("FLASH_Page_Write: Write not enabled!\r\n")
          return 2;
      };
      
      if ( FLASH_Is_Busy() ) {
          //NRF_LOG_DEBUG("FLASH_Page_Write: Busy!\r\n")
          return 3;
      };
      
      if ( FLASH_Page_Is_Empty( pageN) == false ) {
          //NRF_LOG_DEBUG("FLASH_Page_Write: Page already contains data!\r\n")
          return 4;
      }
     
      //NRF_LOG_DEBUG("Write looking good\r\n");
     
      //the command and address
      int address = page_to_address( pageN );
      
      memset(txHalf, 0, sizeof(txHalf));
      
      txHalf[0] = CMD_PAGE_PROGRAM;
      txHalf[1] = (address >> 16) & 0xFF;
      txHalf[2] = (address >> 8)  & 0xFF;
      txHalf[3] =  address        & 0xFF;
    
      uint16_t i = 0;
      
      //write the first 128 bytes
      for( i = 4; i < (128+4); i++ ) { txHalf[i] = wp[i-4]; };
      nrf_drv_spi_transfer(&spi, txHalf, sizeof(txHalf), NULL, 0);
      //wait for at most 200 ms to make sure write completes
      for( i = 0; i < 10; i++ ) {
          nrf_delay_ms(20); 
          if ( FLASH_Is_Busy() ) {
              //wait
          } else {
              break;   
          }
      }
    
      //wait for at most 200 ms to make sure we are good for next write
      for( i = 0; i < 10; i++ ) {
          nrf_delay_ms(20); 
          if ( FLASH_Set_Write_Enable() ) {
              break;
          } else {
              //NRF_LOG_DEBUG("Erase: Not able to write\r\n");
          }
      }
      
      //write the next 128 bytes
      txHalf[3] = 128;
      for( i = 4; i < (128+4); i++ ) { txHalf[i] = wp[i-4+128]; };
      nrf_drv_spi_transfer(&spi, txHalf, sizeof(txHalf), NULL, 0);
    	nrf_delay_ms(100);
      return 0;
    }
    
    
    void FLASH_WriteCustom(uint8_t value)
    {
    		FLASH_Set_Write_Enable();
    		memset(rx5, 0, sizeof(rx5));
    	
    		rx5[0] = CMD_PAGE_PROGRAM;
    		rx5[1] = 0x00;
    		rx5[2] = 0x00;
    		rx5[3] = 0x01;
    		rx5[4] = value;
    		nrf_drv_spi_transfer(&spi, rx5, sizeof(rx5), NULL, 0);
    		nrf_delay_ms(100);
    }
    
    void FLASH_CustomRead()
    {
    		FLASH_Set_Write_Enable();
    		memset(tx4, 0, sizeof(rx4));
    		memset(rx2, 0, sizeof(rx2));
    	
    		rx4[0] = CMD_PAGE_PROGRAM;
    		rx4[1] = 0x00;
    		rx4[2] = 0x00;
    		rx4[3] = 0x01;
    	
    		nrf_drv_spi_transfer(&spi, tx4, sizeof(tx4), cmd, sizeof(rx2));
    		SEGGER_RTT_printf(0, "%d %d\n", *cmd, *(cmd+1));
    }
    
    
    6153.memory.h
     /* 
      * This example is not extensively tested and only 
      * meant as a simple explanation and for inspiration. 
      * NO WARRANTY of ANY KIND is provided. 
      */
    
    #include <stdio.h>
    #include "boards.h"
    #include "app_uart.h"
    #include "app_error.h"
    #include "nrf_delay.h"
    #include "app_mpu_20648.h"
    #include "memory.h"
    #include "nrf_gpio.h"
    #include "app_util_platform.h"
    #include "app_error.h"
    #include <string.h>
    #define NRF_LOG_MODULE_NAME "APP"
    #include "nrf_log.h"
    //#include "nrf_log_ctrl.h"
    #include "memory.h"
    #include "SEGGER_RTT.h"
    
    
    
    
    /*UART buffer size. */
    #define UART_TX_BUF_SIZE 256
    #define UART_RX_BUF_SIZE 1
    uint8_t data_val[256];
    
    /**
     * @brief UART events handler.
     */
    static void uart_events_handler(app_uart_evt_t * p_event)
    {
        switch (p_event->evt_type)
        {
            case APP_UART_COMMUNICATION_ERROR:
                APP_ERROR_HANDLER(p_event->data.error_communication);
                break;
    
            case APP_UART_FIFO_ERROR:
                APP_ERROR_HANDLER(p_event->data.error_code);
                break;
    
            default:
                break;
        }
    }
    
    
    /**
     * @brief UART initialization.
     * Just the usual way. Nothing special here
     */
    static void uart_config(void)
    {
        uint32_t                     err_code;
        const app_uart_comm_params_t comm_params =
        {
            RX_PIN_NUMBER,
            TX_PIN_NUMBER,
            RTS_PIN_NUMBER,
            CTS_PIN_NUMBER,
            APP_UART_FLOW_CONTROL_DISABLED,
            false,
            UART_BAUDRATE_BAUDRATE_Baud115200
        };
    
        APP_UART_FIFO_INIT(&comm_params,
                           UART_RX_BUF_SIZE,
                           UART_TX_BUF_SIZE,
                           uart_events_handler,
                           APP_IRQ_PRIORITY_LOW,
                           err_code);
    
        APP_ERROR_CHECK(err_code);
    }
    
    
    
    void mpu_setup(void)
    {
        ret_code_t ret_code;
        // Initiate MPU driver
        ret_code = mpu_init();
        APP_ERROR_CHECK(ret_code); // Check for errors in return value
        
        // Setup and configure the MPU with intial values
        mpu_config_t p_mpu_config = MPU_DEFAULT_CONFIG(); // Load default values
        p_mpu_config.smplrt_div = 19;   // Change sampelrate. Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV). 19 gives a sample rate of 50Hz
        p_mpu_config.accel_config.afs_sel = AFS_2G; // Set accelerometer full scale range to 2G
        ret_code = mpu_config(&p_mpu_config); // Configure the MPU with above values
        APP_ERROR_CHECK(ret_code); // Check for errors in return value 
    }
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {    
        uint32_t err_code;
    	/*LEDS_CONFIGURE(LEDS_MASK);
    	LEDS_OFF(LEDS_MASK);
        uart_config();*/
       // printf("\033[2J\033[;HMPU simple example. Compiled @ %s\r\n", __TIME__);
      mpu_setup();
    	flash_init();  
      accel_values_t acc_values;
    	gyro_values_t gyro_values;
        uint32_t sample_number = 0;
        while(1)
        {
            // Read accelerometer sensor values
          err_code = mpu_read_accel(&acc_values);
            APP_ERROR_CHECK(err_code);
    			err_code = mpu_read_gyro(&gyro_values);
            APP_ERROR_CHECK(err_code);
    			nrf_delay_ms(100);
    			FLASH_Print_ID();
    		// Clear terminal and print values
       SEGGER_RTT_printf(0,"\033[3;1HSample # %d\r\nX: %06d\r\nY: %06d\r\nZ: %06d\r\n gyrox:%06d\r\n gyroy=%d\r\n gyroz=%d\r\n", ++sample_number, acc_values.x, acc_values.y, acc_values.z,gyro_values.x,gyro_values.y,gyro_values.z);
    		
        }
    }
    
    /** @} */

    spi0 is enabled in config file.

  • vohra alihussain said:
    yes there is activity on spi lines...
    • Could you be more specific? What are you observing?
    • Is Chip select set properly?
    • Is the clock correct?
    • What are you observing on the data lines?
Related