2 Replies Latest reply on Jun 19, 2019 2:49 AM by VinayakS_26

    How to enable the SPI Receive DMA interrupt

    MoNo_2793136

      I am trying to enable the SPI Receive DMA interrupt on the 4343 combo chip.

      I added this function to platform_spi.c file to enable the Rx DMA interrupt:

      static platform_result_t spi_dma_rx( const platform_spi_t* spi, const platform_spi_message_segment_t* message )
      {
          DMA_InitTypeDef dma_init;
          uint32_t loop_count;
          platform_result_t result = PLATFORM_SUCCESS;
          uint32_t pending_intr = 0;

          /* Error check buffers */
          if ((message->rx_buffer == NULL) && (message->tx_buffer == NULL))
              return PLATFORM_ERROR;

          /* Enable DMA peripheral clock */

          RCC->AHB1ENR |= RCC_AHB1Periph_DMA1; // DMA1 for Rx only


          dma_init.DMA_PeripheralBaseAddr = ( uint32_t )&spi->port->DR;
          dma_init.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
          dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
          dma_init.DMA_BufferSize         = message->length;
          dma_init.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;
          dma_init.DMA_Mode               = DMA_Mode_Normal;
          dma_init.DMA_Priority           = DMA_Priority_High;
          dma_init.DMA_FIFOMode           = DMA_FIFOMode_Disable;
          dma_init.DMA_FIFOThreshold      = DMA_FIFOThreshold_1QuarterFull;
          dma_init.DMA_MemoryBurst        = DMA_MemoryBurst_Single;
          dma_init.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;

          wiced_assert( "for debug", message->rx_buffer == NULL ); // only for debugging by mn
          /* Setup RX first */
          DMA_ClearFlag( spi->rx_dma.stream, spi->rx_dma.complete_flags | spi->rx_dma.error_flags );

          DMA_DeInit( spi->rx_dma.stream );

          loop_count = 0;
          while (DMA_GetCmdStatus( spi->rx_dma.stream ) == ENABLE)
          {
              loop_count++;
                if ( loop_count >= (uint32_t) SPI_DMA_CTL_TIMEOUT_LOOPS )
                  return PLATFORM_TIMEOUT;
          }

          dma_init.DMA_Channel            = spi->rx_dma.channel;
          dma_init.DMA_DIR                = DMA_DIR_PeripheralToMemory;
          if (message->rx_buffer != NULL)
          {
              dma_init.DMA_Memory0BaseAddr    = (uint32_t)message->rx_buffer;
              dma_init.DMA_MemoryInc          = DMA_MemoryInc_Enable;
          }

          /* Init and activate RX DMA channel */
          DMA_Init( spi->rx_dma.stream, &dma_init );

          DMA_Cmd( spi->rx_dma.stream, ENABLE );
          loop_count = 0;
          while (DMA_GetCmdStatus( spi->rx_dma.stream ) == DISABLE)
          {
              loop_count++;
              if ( loop_count >= (uint32_t) SPI_DMA_CTL_TIMEOUT_LOOPS )
              {
                  return PLATFORM_TIMEOUT;
              }
          }

          SPI_I2S_DMACmd( spi->port, SPI_I2S_DMAReq_Rx, ENABLE );

       

          DMA_ITConfig(spi->rx_dma.stream, ( DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_FE ) , ENABLE);
          //DMA_ITConfig(spi->rx_dma.stream, DMA_IT_TC | DMA_IT_TE, ENABLE);
          NVIC_SetPriority(spi->rx_dma.irq_vector, 7);
          NVIC_EnableIRQ( spi->rx_dma.irq_vector );

       

         

          return result;
      }

      =====================================================================

      The following is my interrupt service routine:

       

      host_semaphore_type_t spi_rx_complete_sem;
      void platform_spi2_rx_dma_irq( const platform_spi_t* driver )
      {
          int rx_count;
          platform_spi_port_t* spi = (platform_spi_port_t*) driver->port;

        

          if ( (DMA1->LISR & DMA_LISR_TCIF3 ) != 0 ) // check the interrupt
          {
              // Clear the IRQ
              DMA1->LIFCR |= DMA_LISR_TCIF3;
              //driver->last_receive_result = PLATFORM_SUCCESS;
          }

          // Check for error
          if ( (  DMA1->LISR & (DMA_LISR_TEIF3 | DMA_LISR_FEIF3 | DMA_LISR_DMEIF3) ) != 0 )
          {
              // Clear the DMA interrupt's errors
              DMA1->LIFCR |= (DMA_LISR_TEIF3 | DMA_LISR_FEIF3 | DMA_LISR_DMEIF3);

              //driver->last_receive_result = PLATFORM_ERROR;
          }


      }

      =======================================================================

      I added the following code snippet  to the file platform.c

      WWD_RTOS_DEFINE_ISR( spi2_rx_dma_irq )

      {

          platform_spi2_rx_dma_irq( &platform_spi_peripherals[WICED_SPI_2] );

      }

       

      WWD_RTOS_MAP_ISR( spi2_rx_dma_irq, DMA1_Stream3_irq )

      =============================================================

      The above steps should be sufficient to enable the invocation of the SPI DMA IRQ. But the IRQ is never invoke. However, the Rx DMA runs to completion since I can see that the stream->NDTR count drops to zero.

      ==========================================================

       

      What is missing in the above step that prevents the invocation of the DMA ISR?

      Thanks, Mohammad