MISO line mimics the MOSI line in SPIM configuration sdk 17.1.0

Hi,

When I looked at the SPI lines using the oscilloscope, I saw that the MISO line had the same signal as the MOSI line. As you can see from the image, basically SPI configuration works properly. Before message transfer CS pin goes low, and after that, the MOSI line works. I can read message that I sent using the oscilloscope.

What can be the problem with the MISO line signal reflecting the MOSI line signal? The SPI config stage CPOL = 0, CPAH = 1, I am using a 2 MHz clock signal. Thanks for your help.

  • Thanks for your reply. After reading the discussion that you share, I will update my findings.

  • Apart from all the devzone posts we've made over the years on the ADS129x some of these older links might be worth looking at:

    5809-biopotential-signal-library

    starcat/hackeeg

    stm32-diy-board-with-ads1299-sparkyeeg

    openeeg.sourceforge.net

  • Hi, Hmolesworth. I configured SPI pins before assigning them via PSEL, but nothing changed.  I have read the discussion you shared and added some related parts to the code. So, I am seeing just 0x00. I do not know what I should do. Are there any other offers to help find a solution to this problem?

    With the latest config, I am seeing this. 

    Turquoise -> MISO
    Purple -> MOSI

    Yellow-> Clock
    Dark Blue -> CS



  • The display would be easier to read if you could separate the traces so they don't overlap. In case you are using S0S1 (default SPIM drive settings), always start with H0H1; try this perhaps:

        // Set High-drive pin mode for SPI
        nrf_gpio_cfg(PIN_SCK,  NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
        nrf_gpio_cfg(PIN_MOSI, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
        nrf_gpio_cfg(PIN_CS,   NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);

    PULLUP is not strictly necessary, NOPULL could be used instead; H0H1 is the important part.

    Worth also trying to start with a slower clock before increasing clock rate:

            spi_config.frequency = NRF_DRV_SPI_FREQ_500K;  // Ensure less than 4 clk cycles for ADS1292
            spi_config.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST;
            spi_config.mode      = NRF_DRV_SPI_MODE_1;
            APP_ERROR_CHECK(nrf_drv_spi_init(&mAfeSpiInstance, &spi_config, afe_spi_event_handler, NULL));
    

    The different parts require power-up handling, as an example:

            // Enable ADS1292 AFE - Power on & remove reset
            nrf_delay_ms(ADS_POWER_RAMP_TIME_MSECS); // Delay about 30 msecs to allow regulator to charge capacitance
            DEACTIVATE_ADS_RESET_PIN;           // Release active-low combined /Reset and /Powerdown
            nrf_delay_ms(1000);                 // Delay 1 sec as per data sheet
            ACTIVATE_ADS_RESET_PIN;             // Activate active-low combined /Reset and /Powerdown
            nrf_delay_ms(2);                    // Delay to allow ADS internal clock to start
            DEACTIVATE_ADS_RESET_PIN;           // Release active-low combined /Reset and /Powerdown
            nrf_delay_us(200);                  // Delay to allow 18 tclk minimum
    
        AdsReset();                                      // Reset ADS
        AdsSendCmd(ADS_CMND_SDATAC);                     // Stop continuous mode
    

    This is a bare-bones segment (ADS1292, similar) in case it's of any help:

    // The SPI master implements EasyDMA for reading and writing of data packets from and to the DATA RAM
    // without CPU involvement.
    // The RXD.PTR and TXD.PTR point to the RXD buffer (receive buffer) and TXD buffer (transmit buffer)
    // respectively. RXD.MAXCNT and TXD.MAXCNT specify the maximum number of bytes allocated to the buffers.
    // The SPI master will automatically stop transmitting after TXD.MAXCNT bytes have been transmitted and
    // RXD.MAXCNT bytes have been received. If TXD.MAXCNT is larger than RXD.MAXCNT, the superfluous
    // received bytes will be ignored. If RXD.MAXCNT is larger than TXD.MAXCNT, the remaining transmitted
    // bytes will contain the value defined in the ORC register.
    // If the RXD.PTR and the TXD.PTR are not pointing to the Data RAM region, an EasyDMA transfer may result
    // in a HardFault or RAM corruption.
    // The .PTR and .MAXCNT registers are double-buffered. They can be updated and prepared for the next
    // transmission immediately after having received the STARTED event.
    // The ENDRX/ENDTX event indicate that EasyDMA has finished accessing respectively the RX/TX buffer in
    // RAM. The END event gets generated when both RX and TX are finished accessing the buffers in RAM.
    // EasyDMA array list
    // The EasyDMA array list can be represented by the data structure ArrayList_type. This data structure
    // includes only a buffer with size equal
    // to Channel.MAXCNT. EasyDMA will use the Channel.MAXCNT register to determine when the buffer
    // is full. Replace 'Channel' by the specific data channel you want to use, for instance 'NRF_SPIM->RXD',
    // 'NRF_SPIM->TXD', 'NRF_TWIM->RXD', etc.
    // The Channel.MAXCNT register cannot be specified larger than the actual size of the buffer. If
    // Channel.MAXCNT is specified larger than the size of the buffer, the EasyDMA channel may overflow the
    // buffer.
    // This array list does not provide a mechanism to explicitly specify where the next item in the list is located.
    // Instead, it assumes that the list is organized as a linear array where items are located one after the other in
    // RAM.
    //
    // SPI master transaction sequence
    // ===============================
    // An SPI master transaction consists of a sequence started by the START task followed by a number of
    // events, and finally the STOP task.
    // An SPI master transaction is started by triggering the START task. The ENDTX event will be generated
    // when the transmitter has transmitted all bytes in the TXD buffer as specified in the TXD.MAXCNT register.
    // The ENDRX event will be generated when the receiver has filled the RXD buffer, i.e. received the last
    // possible byte as specified in the RXD.MAXCNT register.
    // Following a START task, the SPI master will generate an END event when both ENDRX and ENDTX have
    // been generated.
    // The SPI master is stopped by triggering the STOP task. A STOPPED event is generated when the SPI
    // master has stopped.
    // If the ENDRX event has not already been generated when the SPI master has come to a stop, the SPI
    // master will generate the ENDRX event explicitly even though the RX buffer is not full.
    // If the ENDTX event has not already been generated when the SPI master has come to a stop, the SPI
    // master will generate the ENDTX event explicitly even though all bytes in the TXD buffer, as specified in the
    // TXD.MAXCNT register, have not been transmitted.
    // The SPI master is a synchronous interface, and for every byte that is sent, a different byte will be received at
    // the same time
    //
    // Master mode pin configuration
    // =============================
    // The SCK, MOSI, and MISO signals associated with the SPI master are mapped to physical pins according to
    // the configuration specified in the PSEL.SCK, PSEL.MOSI, and PSEL.MISO registers respectively.
    // The PSEL.SCK, PSEL.MOSI, and PSEL.MISO registers and their configurations are only used as long as
    // the SPI master is enabled, and retained only as long as the device is in ON mode. PSEL.SCK, PSEL.MOSI
    // and PSEL.MISO must only be configured when the SPI master is disabled.
    // To secure correct behavior in the SPI, the pins used by the SPI must be configured in the GPIO peripheral
    #if defined(USING_NORDIC_SPIM_DRIVERS)
    #else
    static void spiInit(NRF_SPIM_Type * const pSPIM, const IRQn_Type IRQn, const uint32_t IRQpriority)
    {
    //spi_config.mode      = NRF_DRV_SPI_MODE_1;
      pSPIM->ENABLE = 0;                        // disable SPI
      NRF_P0->PIN_CNF[ADS_CS_PIN]   = 0x301;  // output, high drive high and low H0H1
      NRF_P0->PIN_CNF[ADS_SCK_PIN]  = 0x301;  // output, high drive high and low H0H1
      NRF_P0->PIN_CNF[ADS_MOSI_PIN] = 1;      // output, standard drive S0S1
      NRF_P0->PIN_CNF[ADS_MISO_PIN] = 0;      // input pin, input buffer connected, no pull, S0S1, sense disabled
      NRF_P0->OUTSET = 1 << ADS_CS_PIN;       // deactivate by setting chip select high
      pSPIM->PSEL.SCK   = ADS_SCK_PIN;
      pSPIM->PSEL.MOSI  = ADS_MOSI_PIN;
      pSPIM->PSEL.MISO  = ADS_MISO_PIN;
      pSPIM->CONFIG = 2;                  // CPOL 0 -- clock polarity active high, CPHA 1 -- sample on trailing clock edge, send Msb first
      pSPIM->FREQUENCY = NRF_DRV_SPI_FREQ_500K;  // Ensure less than 4 clk cycles for ADS1292
      pSPIM->ORC = 0xFF;                     // Unused Tx bytes, set all bits high
    
      pSPIM->EVENTS_ENDTX = 0;
      pSPIM->EVENTS_ENDRX = 0;
      pSPIM->EVENTS_END   = 0;
      // Disable all interrupts
      pSPIM->INTENCLR = 0xFFFFFFFFUL;
      // Enable selected interrupts
      pSPIM->INTENSET = 0x040;   // END
      //pSPIM->INTENSET = 0x010;   // END_RX
      //pSPIM->INTENSET = 0x100;   // END_TX
      
      // Set interrupt priority and enable interrupt
      NVIC_SetPriority(IRQn, IRQpriority);
      NVIC_ClearPendingIRQ(IRQn);
      NVIC_EnableIRQ(IRQn);
    
      mSpiInterruptCounter = 0UL;
      pSPIM->ENABLE = 7;               // enable SPI
    }
    
    static void spiTransfer(uint8_t const * p_tx_buffer,
                            uint8_t         tx_buffer_length,
                            uint8_t       * p_rx_buffer,
                            uint8_t         rx_buffer_length)
    {
      NRF_SPIM0->EVENTS_ENDTX = 0;
      NRF_SPIM0->EVENTS_ENDRX = 0;
      NRF_SPIM0->EVENTS_END   = 0;
    
      NRF_SPIM0->ENABLE = 7;               // enable SPI
      NRF_SPIM0->TXD.PTR = (uint32_t)p_tx_buffer;
      NRF_SPIM0->TXD.MAXCNT = tx_buffer_length;
      NRF_SPIM0->RXD.PTR = (uint32_t)p_rx_buffer;
      NRF_SPIM0->RXD.MAXCNT = rx_buffer_length;
      NRF_P0->OUTCLR = 1 << ADS_CS_PIN;    // drive cs low to initiate spi comm
      nrf_delay_us(10);
      NRF_SPIM0->TASKS_START = 1;
      while(!NRF_SPIM0->EVENTS_ENDTX);     // last byte transmitted
      while(!NRF_SPIM0->EVENTS_ENDRX);     // last byte received
      NRF_SPIM0->TASKS_STOP = 1;
      nrf_delay_us(10);
      NRF_P0->OUTSET = 1 << ADS_CS_PIN;
      while(!NRF_SPIM0->EVENTS_STOPPED);
      //NRF_SPIM0->ENABLE = 0;               // disable SPI
    }
    

  • Thanks for your quick reply, hmolesworth. I tried adding reasonable delays to the power-up sequence, but I am getting the same signal from the MISO line. I have seen articles about power in different places. I am not using power for ADS1299 via nRF. Could this be causing the problem? I am powering the ADS1299 DK with an external device. I tried with a lower clock frequency, but it did not change anything. Again, thanks for your reply.

Related