AnsweredAssumed Answered

Problem with SPI slave using interrupts on STM32F107

Question asked by a.felix on Oct 14, 2015
IDE CooCox 1.7.8

Hi
brief: I try to build up a SPI communication line between a STM32F407 (Master) and STM32F107 (Slave). It is a three wire line; not using NSS. Using SPI2 on both devices. On master, clock, TX and RX is working well. On slave TX is working, but RX not.

detail: Below are some snips of my spi code. The slave should uses SPI2_IRQHandler to move the received data into a fifo buffer, but SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_RXNE) never gets set. TX is working. And the same function (RX and TX) is working on the STM32F4. What is going wrong with my F107 implementation?

I checked the signal with my scope. Its fine!
Thanks for help!

Snip of spi2_slave.h
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _SPI2_SLAVE_H_
#define _SPI2_SLAVE_H_

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Exported types ------------------------------------------------------------*/

/* Exported constants --------------------------------------------------------*/
#define SPI2_SCK_PIN         GPIO_Pin_13
#define SPI2_SCK_GPIO_PORT   GPIOB
#define SPI2_SCK_GPIO_CLK    RCC_APB2Periph_GPIOB

#define SPI2_MISO_PIN        GPIO_Pin_14
#define SPI2_MISO_GPIO_PORT  GPIOB
#define SPI2_MISO_GPIO_CLK   RCC_APB2Periph_GPIOB

#define SPI2_MOSI_PIN        GPIO_Pin_15
#define SPI2_MOSI_GPIO_PORT  GPIOB
#define SPI2_MOSI_GPIO_CLK   RCC_APB2Periph_GPIOB

#define SPI2_NSS_PIN         GPIO_Pin_12
#define SPI2_NSS_GPIO_PORT   GPIOB
#define SPI2_NSS_GPIO_CLK    RCC_APB2Periph_GPIOB

#define SPI2_CLK             RCC_APB1Periph_SPI2
#define SPI2_AF_CLK          RCC_APB2Periph_AFIO
...
END


Snip of spi2_slave.c
...
/* Private functions ---------------------------------------------------------*/
void spi2_init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    SPI_InitTypeDef SPI_InitStructure;

    /* Initialize early */
    fifo_init(spi2_RxFifo, (void *) spi2_RxBuffer, sizeof(spi2_RxBuffer));
    fifo_init(spi2_TxFifo, (void *) spi2_TxBuffer, sizeof(spi2_TxBuffer));

    /* DeInit */
    SPI_I2S_DeInit(SPI2);

    /* Enable Peripheral clock */
    RCC_APB1PeriphClockCmd(SPI2_CLK, ENABLE);

    /* Enable AF clock */
    RCC_APB2PeriphClockCmd(SPI2_AF_CLK, ENABLE);

    /* Enable GPIO clock */
    RCC_APB2PeriphClockCmd(SPI2_SCK_GPIO_CLK, ENABLE);
    RCC_APB2PeriphClockCmd(SPI2_MISO_GPIO_CLK, ENABLE);
    RCC_APB2PeriphClockCmd(SPI2_MOSI_GPIO_CLK, ENABLE);
    RCC_APB2PeriphClockCmd(SPI2_NSS_GPIO_CLK, ENABLE);

    GPIO_InitStructure.GPIO_Pin = SPI2_SCK_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(SPI2_SCK_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SPI2_MOSI_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(SPI2_MOSI_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SPI2_MISO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(SPI2_MISO_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SPI2_NSS_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(SPI2_NSS_GPIO_PORT, &GPIO_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; /**< set prio later!!! */
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    //SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; /**< SPI frequency is APB2 frequency 36MHz / 32 = 1.125 MHz */
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; /**< as slave, data sampled at first edge */
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; /**< as slave, clock is low when idle */
    SPI_InitStructure.SPI_CRCPolynomial = 0; /**< no hardware crc */
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; /**< one packet of data is 8 bits wide */
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; /**< set to full duplex mode, seperate MOSI and MISO lines */
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; /**< data is transmitted MSB first */
    SPI_InitStructure.SPI_Mode = SPI_Mode_Slave; /**< (as slave ??) as master, transmit in master mode, NSS pin has to be always high */
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; /**< set the NSS management */
    SPI_Init(SPI2, &SPI_InitStructure);

    spi2_tx_interrupt_disable();
    spi2_rx_interrupt_enable();

    SPI_Cmd(SPI2, ENABLE);
}

...
void SPI2_IRQHandler(void) {
    /* Receive flag */
    if (SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_RXNE) != RESET) {
/* never gets into this state :( */
        uint8_t rx;
        /* Receive data and add to fifo */
        rx = (uint8_t)SPI_I2S_ReceiveData(SPI2); // Receive the character
        fifo_write(spi2_RxFifo, &rx, 1); // Place in reception fifo
    }
    /* Transmit flag set */
    if (SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_TXE) != RESET) {
        uint8_t tx;
        /* Check anything to send? */
        if (fifo_read(spi2_TxFifo, &tx, 1) == 1) {
            /* Transmit the character */
            SPI_I2S_SendData(SPI2, (uint16_t) tx);
        } else {
            /* Suppress interrupt when empty */
            spi2_tx_interrupt_disable();
        }
    }
}

void spi2_tx_interrupt_enable(void) {
    SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE);
}

void spi2_tx_interrupt_disable(void) {
    SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, DISABLE);
}

void spi2_rx_interrupt_enable(void) {
    SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);
}

void spi2_rx_interrupt_disable(void) {
    SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, DISABLE);
}
...
END

Outcomes