How to use GPIO external interrupt

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
MaCa_2922036
Level 3
Level 3
10 replies posted 10 sign-ins 5 replies posted

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

0 Likes
8 Replies
Zhengbao_Zhang
Moderator
Moderator
Moderator
250 sign-ins First comment on KBA 10 questions asked

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. 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=0x00;

        dma_rx_buf=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);

}

0 Likes

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

0 Likes

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 ),
        },
    }

};

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

0 Likes

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.

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.

0 Likes

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 },

};

0 Likes