8 Replies Latest reply on Mar 24, 2020 11:53 PM by ZhengbaoZ_96

    How to use GPIO external interrupt

    MaCa_2922036

      Hello,

       

      I have an SPI communication between my 1LD Wifi/BT module and another MCU.

      This SPI use SPI5 hardware and works with DMA for Tx and Rx.

      I want to use the chip select (pin 57, PB1, with external PullUp) configured as input pin with external interrupt.

       

      I tried the follow configuration, but it never enter in the interrupt handler

      Is the right use for configuration of external interrupt ?

       

      Option 1

      void init_NssPin (void)

      {

            NssGpio.pin_number = 1;

            NssGpio.port = GPIOB;

             platform_gpio_init( &NssGpio, INPUT_HIGH_IMPEDANCE );

             platform_result_t res;

             res = platform_gpio_irq_enable (&NssGpio, IRQ_TRIGGER_RISING_EDGE, ISR_SpiNss_handler, 0 );

             WPRINT_APP_INFO( ( "result of NSS IRQ init = %d\n",res ) ); // note: result code give me 6010 which mean NO_EFFECT ...

      }

       

      void ISR_SpiNss_handler( void* arg )

      {

           v_SetLedState(0,1); // debug:  LED_INDEX_1 set to high

      }

       

       

      I aslo tried a second option with ExtInt functions and force the mapping of ISR function:

      Option 2

       

      SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource1);   

      ExtIntSpiNss.EXTI_Line = EXTI_Line1;    

      ExtIntSpiNss.EXTI_LineCmd = ENABLE;   

      ExtIntSpiNss.EXTI_Mode = EXTI_Mode_Interrupt;   

      ExtIntSpiNss.EXTI_Trigger = EXTI_Trigger_Rising;    

      EXTI_Init(&ExtIntSpiNss);    

       

      /* Add IRQ vector to NVIC */    

      NVIC_InitTypeDef NVIC_InitStruct;   

      NVIC_InitStruct.NVIC_IRQChannel = EXTI1_IRQn;    

      NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01;   

      NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00;   

      NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;    

      NVIC_Init(&NVIC_InitStruct);

       

      WWD_RTOS_DEFINE_ISR ( ISR_SpiNss_handler )

      {

           v_SetLedState(0,1); // debug:  LED_INDEX_1 set to high

      }

      WWD_RTOS_MAP_ISR(ISR_SpiNss_handler, EXTI1_irq)

       

      But it also don't work.

       

      Could you help me ?

       

       

      Note: I use WICED v.6.2

        • 1. Re: How to use GPIO external interrupt
          ZhengbaoZ_96

          Hello:

           

          I have two questions about this thread:

          1.  What is the communication interface for wifi chip 1DL ?  is it SDIO or SPI ?

          2.  Is the interrupt pin used to receive interrupt from Wifi chip ?  like connecting with the OOB pin.

               or you just test this SPI pin to see if it could work as an external INT pin .

          1 of 1 people found this helpful
          • 2. Re: How to use GPIO external interrupt
            MaCa_2922036

            1. The communication is SPI.

            2. the interrupt is received by the 1LD modul. This interrupt is set on the Chip Select line of the SPI in order to detect the begin and the end of the SPI message.

             

            Here is my code for initialisation of SPI and DMA used for Rx and Tx buffer of SPI.

             

             

            static void configure_spi(void)

            {

                GPIO_InitTypeDef GPIO_InitStruct = {0};

                SPI_InitTypeDef s_SPI_InitStruct;

             

                // CLK + MOSI Pin Init

                GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_1;

                GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;

                GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;

                GPIO_InitStruct.GPIO_Speed = GPIO_High_Speed;

                GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;

                GPIO_Init(GPIOB, &GPIO_InitStruct);

                GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF6_SPI5);

                GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF6_SPI5);

             

                // NSS Pin Init

                GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;

                GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;

                GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;

                GPIO_InitStruct.GPIO_Speed = GPIO_High_Speed;

                GPIO_Init(GPIOB, &GPIO_InitStruct);

                v_SetLedState(0,0); // LED_INDEX_1 (TP618) set to low  ///@debug

             

                NssGpio.pin_number = 1;

                NssGpio.port = GPIOB;

                platform_gpio_init( &NssGpio, INPUT_HIGH_IMPEDANCE );

                platform_result_t res;

                res = platform_gpio_irq_enable (&NssGpio, IRQ_TRIGGER_RISING_EDGE, ISR_SpiNss_handler, 0 );

                WPRINT_APP_INFO( ( "result of NSS IRQ init = %d\n",res ) );

             

                // MISO Pin Init

                GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;

                GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;

                GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;

                GPIO_InitStruct.GPIO_Speed = GPIO_High_Speed;

                GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;

                GPIO_Init(GPIOA, &GPIO_InitStruct);

                GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF6_SPI5);

             

                s_SPI_InitStruct.SPI_Mode = SPI_Mode_Slave;

                s_SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

                s_SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;

                s_SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;

                s_SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;

                s_SPI_InitStruct.SPI_NSS = SPI_NSS_Hard;

                s_SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;

             

                /* Be sure to clear Rx register */

                if (SPI_I2S_GetFlagStatus(SPI5, SPI_I2S_FLAG_RXNE) == SET)

                {

                    uint8_t dummy = SPI5->DR;

                }

                else{}

             

                SPI_Init(SPI5, &s_SPI_InitStruct);

             

                /* Init variables */

                i8u_SPI_CmdRequestFlag.byte = 0x00;

            }

             

             

            static void configure_spi_dma(void)

            {

                uint8_t i = 0;

                DMA_InitTypeDef dma_is;

             

                RCC_APB2PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

             

                /* init DMA buffer */

                for(i=0; i<SPI_MSG_SIZE; i++)

                {

                    dma_tx_buf[i]=0x00;

                    dma_rx_buf[i]=0x00;

                }

             

                /*** Rx DMA Stream ***/

                dma_is.DMA_Channel = DMA_Channel_7;

                dma_is.DMA_Memory0BaseAddr = (uint32_t)dma_rx_buf;

                dma_is.DMA_PeripheralBaseAddr = (uint32_t)(&(SPI5->DR));

                dma_is.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

                dma_is.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

                dma_is.DMA_DIR = DMA_DIR_PeripheralToMemory;

                dma_is.DMA_Mode = DMA_Mode_Normal; // DMA_Mode_Circular;//DMA_Mode_Normal;

                dma_is.DMA_MemoryInc = DMA_MemoryInc_Enable;

                dma_is.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

                dma_is.DMA_BufferSize = SPI_MSG_SIZE;

                dma_is.DMA_Priority = DMA_Priority_High;

                dma_is.DMA_MemoryBurst = DMA_MemoryBurst_Single;

                dma_is.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

                dma_is.DMA_FIFOMode = DMA_FIFOMode_Disable;

             

                DMA_ClearFlag(DMA2_Stream5, DMA_FLAG_TCIF5 | DMA_FLAG_HTIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_DMEIF5 | DMA_FLAG_FEIF5);

                DMA_DeInit(DMA2_Stream5);

                tx_thread_sleep(10);

                DMA_Init(DMA2_Stream5, &dma_is);

             

                DMA_ITConfig(DMA2_Stream5, DMA_IT_TC, DISABLE); //test interrupt on Chip Select pin instead of interrupt on DMA Rx buffer full  // DMA_ITConfig(DMA2_Stream5, DMA_IT_TC, ENABLE);

             

                DMA_SetCurrDataCounter(DMA2_Stream5, SPI_MSG_SIZE);

             

                NVIC_InitTypeDef NVIC_InitStruct;

                NVIC_InitStruct.NVIC_IRQChannel = DMA2_Stream5_IRQn;

                NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;

                NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00;

                NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;

                NVIC_Init(&NVIC_InitStruct);

             

                DMA_Cmd(DMA2_Stream5, ENABLE);

                tx_thread_sleep(10);

             

                /*** Tx DMA Stream ***/

                dma_is.DMA_Channel = DMA_Channel_2;

                dma_is.DMA_Memory0BaseAddr = (uint32_t)dma_tx_buf;

                dma_is.DMA_PeripheralBaseAddr = (uint32_t)(&(SPI5->DR));

                dma_is.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

                dma_is.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

                dma_is.DMA_DIR = DMA_DIR_MemoryToPeripheral;

                dma_is.DMA_Mode = DMA_Mode_Normal; //DMA_Mode_Circular;//DMA_Mode_Normal;

                dma_is.DMA_MemoryInc = DMA_MemoryInc_Enable;

                dma_is.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

                dma_is.DMA_BufferSize = SPI_MSG_SIZE;

                dma_is.DMA_Priority = DMA_Priority_Medium;

                dma_is.DMA_MemoryBurst = DMA_MemoryBurst_Single;

                dma_is.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

                dma_is.DMA_FIFOMode = DMA_FIFOMode_Disable;

             

                DMA_ClearFlag(DMA2_Stream4, DMA_FLAG_TCIF4 | DMA_FLAG_HTIF4 | DMA_FLAG_TEIF4 | DMA_FLAG_DMEIF4 | DMA_FLAG_FEIF4);

                DMA_DeInit(DMA2_Stream4);

                tx_thread_sleep(10);

                DMA_Init(DMA2_Stream4, &dma_is);

                DMA_SetCurrDataCounter(DMA2_Stream4, SPI_MSG_SIZE);

             

                DMA_Cmd(DMA2_Stream4, ENABLE);

                tx_thread_sleep(10);

            }

            • 3. Re: How to use GPIO external interrupt
              ZhengbaoZ_96

              got it, I will try to find if we have same setting in the release.

              • 4. Re: How to use GPIO external interrupt
                ZhengbaoZ_96

                hello:

                 

                I think you already have the critical define in this thread, I just attach what I found in the release.

                43xxx_Wi-Fi\WICED\platform\MCU\STM32F4xx

                /* Setup DMA for SPI2 RX */
                DMA_DeInit( DMA1_Stream3 );
                dma_init_structure.DMA_Channel        = DMA_Channel_0;
                dma_init_structure.DMA_PeripheralBaseAddr = (uint32_t) &SPI2->DR;
                dma_init_structure.DMA_Memory0BaseAddr= 0;

                 

                below is to enable :

                 

                /* Must be lower priority than the value of configMAX_SYSCALL_INTERRUPT_PRIORITY */
                /* otherwise FreeRTOS will not be able to mask the interrupt */
                /* keep in mind that ARMCM3 interrupt priority logic is inverted, the highest value */
                /* is the lowest priority */
                NVIC_EnableIRQ( SPI_BUS_TX_DMA_STREAM );

                 

                /* Enable DMA for TX */
                SPI_I2S_DMACmd( SPI2, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE );

                 

                in platform.c c

                  the struture describes the connections :

                 

                [WICED_SPI_2]  =
                    {
                        .port              = SPI2,
                        .gpio_af           = GPIO_AF_SPI2,
                        .peripheral_clock_reg  = RCC_APB1Periph_SPI2,
                        .peripheral_clock_func = RCC_APB2PeriphClockCmd,
                        .pin_mosi          = &platform_gpio_pins[WICED_GPIO_31],
                        .pin_miso          = &platform_gpio_pins[WICED_GPIO_30],
                        .pin_clock         = &platform_gpio_pins[WICED_GPIO_29],
                        .tx_dma =
                        {
                            .controller    = DMA1,
                            .stream        = DMA1_Stream4,
                            .channel       = DMA_Channel_0,
                            .irq_vector    = DMA1_Stream4_IRQn,
                            .complete_flags= DMA_HISR_TCIF5,
                            .error_flags   = ( DMA_HISR_TEIF5 | DMA_HISR_FEIF5 | DMA_HISR_DMEIF5 ),
                        },
                        .rx_dma =
                        {
                            .controller    = DMA1,
                            .stream        = DMA1_Stream3,
                            .channel       = DMA_Channel_0,
                            .irq_vector    = DMA1_Stream3_IRQn,
                            .complete_flags= DMA_LISR_TCIF0,
                            .error_flags   = ( DMA_LISR_TEIF0 | DMA_LISR_FEIF0 | DMA_LISR_DMEIF0 ),
                        },
                    }

                };

                1 of 1 people found this helpful
                • 5. Re: How to use GPIO external interrupt
                  MaCa_2922036

                  I am Ok with this configuration of DMA, but I don't see where you configure the Chip select pin of the SPI ?

                  So I don't understand the interrupt behavior:

                  => does your Rx DMA interrupt will trig when the DMA buffer is full (no DMA size is defined in your example) ?

                  => or does your Rx DMA interrupt will trig when the ChipSelect will be disable ?

                   

                  I forgot to precise that in my case the 1LD module is the slave in this SPI communication.

                   

                  Thanks

                  • 6. Re: How to use GPIO external interrupt
                    ZhengbaoZ_96

                     

                     

                     

                    RCC_PCLK1Config( RCC_HCLK_Div2 ); /* Set clock to 18MHz (assuming 72MHz STM32 system clock) */

                     

                    /* Enable SPI_SLAVE DMA clock */
                    RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_DMA1, ENABLE );

                     

                    /* Enable SPI_SLAVE Periph clock */
                    RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );

                     

                    /* Enable SYSCFG. Needed for selecting EXTI interrupt line */
                    RCC_APB2PeriphClockCmd( RCC_APB2Periph_SYSCFG, ENABLE );

                     

                    /* Setup the interrupt input for WLAN_IRQ */

                    #ifndef WWD_SPI_IRQ_FALLING_EDGE

                    platform_gpio_init( &wifi_spi_pins[WWD_PIN_SPI_IRQ], INPUT_HIGH_IMPEDANCE );
                    platform_gpio_irq_enable( &wifi_spi_pins[WWD_PIN_SPI_IRQ], IRQ_TRIGGER_RISING_EDGE, spi_irq_handler, 0 );

                    #else /* WWD_SPI_IRQ_FALLING_EDGE */

                    platform_gpio_init( &wifi_spi_pins[WWD_PIN_SPI_IRQ], INPUT_PULL_UP );
                    platform_gpio_irq_enable( &wifi_spi_pins[WWD_PIN_SPI_IRQ], IRQ_TRIGGER_FALLING_EDGE, spi_irq_handler, 0 );

                    #endif /* WWD_SPI_IRQ_FALLING_EDGE */

                     

                    /* Setup SPI slave select GPIOs */
                    platform_gpio_init( &wifi_spi_pins[WWD_PIN_SPI_CS], OUTPUT_PUSH_PULL );
                    platform_gpio_output_high( &wifi_spi_pins[WWD_PIN_SPI_CS] );

                     

                    all the config include CS of SPI is here.

                    1 of 1 people found this helpful
                    • 7. Re: How to use GPIO external interrupt
                      MaCa_2922036

                      Hello,

                       

                      I don't uderstand why you put the IRQ_PIN as interrupt and the CS pin as output ?

                      What is the hardware pin behind your PIN_SPI_IRQ ?

                       

                      In case of SPI slave device, the CS should be set as input, no ?

                      and the interrupt activated on the CS pin.

                      • 8. Re: How to use GPIO external interrupt
                        ZhengbaoZ_96

                        hello:

                          I think in our code we set SPI2 as communication interface between F4xx and wifi chip.

                        and it is a master mode:

                            /* Setup SPI */

                            spi_init.SPI_Direction         = SPI_Direction_2Lines_FullDuplex;

                            spi_init.SPI_Mode              = SPI_Mode_Master;

                             ...................

                            /* Init SPI and enable it */

                            SPI_Init( SPI2, &spi_init );

                         

                        then we use another pin acting as INT input from WLAN chip , didn't let CS pin multiplexed as DMA INT.

                         

                            /* Setup the interrupt input for WLAN_IRQ */

                            platform_gpio_init( &wifi_spi_pins[WWD_PIN_SPI_IRQ], INPUT_HIGH_IMPEDANCE );

                            platform_gpio_irq_enable( &wifi_spi_pins[WWD_PIN_SPI_IRQ], IRQ_TRIGGER_RISING_EDGE, spi_irq_handler, 0 );

                         

                        /* Wi-Fi gSPI bus pins. Used by WICED/platform/STM32F4xx/WWD/wwd_SPI.c */

                        const platform_gpio_t wifi_spi_pins[] =

                        {

                            [WWD_PIN_SPI_IRQ ] = { GPIOC,  9 },

                            [WWD_PIN_SPI_CS  ] = { GPIOB, 12 },

                            [WWD_PIN_SPI_CLK ] = { GPIOB, 13 },

                            [WWD_PIN_SPI_MOSI] = { GPIOB, 15 },

                            [WWD_PIN_SPI_MISO] = { GPIOB, 14 },

                        };