Pika
Pika

Reputation: 51

STM32F072RB does not receive/send data over SPI in slave mode

I am using the STM32F072RB uC to receive and transmit data over SPI2 in slave mode with the following configuration:

CR1 = 0x0078
CR2 = 0x0700
AFRH = 0x55353500
MODER = 0xa2a0556a

The register APB1ENR is also properly configured.

The current program just checks the RXNE flag, reads the received data from DR and sends a random value writing to DR.

The status register when I receive data has the following value:

SR = 0x1403

The master sends data properly and I checked the signals at the slave pins (clock phase and polarity are identical on both sides and the NSS signal is cleared before sending SCK and data over MOSI).

I even configured the pins as inputs and I know I could read any digital signal the master could send. With the current configuration it seems the slave receives something because the RXNE is set when the master sends data but the read value is always 0x00.

I have tried different configurations (software/hardware NSS, different data sizes, etc.) but I always get 0x00. Moreover, the random value I send after reading DR is not sent to the outputs.

This is my current function, which is called continuously:

unsigned char spi_rx_slave(unsigned char spiPort, unsigned char *receiveBuffer)
{
    uint8_t temp;
    static unsigned long sr;
    if (!spi_isOpen(spiPort))
    {
        sendDebug("%s() Error: spiPort not in use!\r\n",__func__);
        return false;
    }
    if (spiDescriptor[spiPort]->powerdown == true)
    {
        sendDebug("%s() Error: spiPort in powerdown!\r\n",__func__);
        return false;
    }
    /* wait till spi is not busy anymore */
    while((spiDescriptor[spiPort]->spiBase->SR) & SPI_SR_BSY)
    {
        sendDebug("SPI is busy(1)\r\n");
        vTaskDelay(2);
    }
    sendDebug("CR1 = 0x%04x, ", spiDescriptor[spiPort]->spiBase->CR1);
    sendDebug("CR2 = 0x%04x, ", spiDescriptor[spiPort]->spiBase->CR2);
    sendDebug("AFRH address = 0x%08x, AFRH value = %08x, ", (unsigned long*)(GPIOB_BASE+0x24), *(unsigned long*)(GPIOB_BASE+0x24));
    sendDebug("MODER address = 0x%08x, MODER value = %08x\r\n", (unsigned long*)(GPIOB_BASE), *(unsigned long*)(GPIOB_BASE));
    sr = spiDescriptor[spiPort]->spiBase->SR;
    while(sr & SPI_SR_RXNE)
    {
        /* get RX byte */
        temp = *(uint8_t *)&(spiDescriptor[spiPort]->spiBase->DR);
        spiDescriptor[spiPort]->spiBase->DR = 0x53;
        sendDebug("-------->DR address = 0x%08x, data received: 0x%02x\r\n", &spiDescriptor[spiPort]->spiBase->DR, temp);
        sendDebug("SR = 0x%04x\r\n", sr);
        vTaskDelay(1);
        sr = spiDescriptor[spiPort]->spiBase->SR;
    }
    while((spiDescriptor[spiPort]->spiBase->SR) & SPI_SR_BSY)
    {
        sendDebug("SPI is busy(2)\r\n");
        vTaskDelay(2);
    }
    return true;
}

What am I doing wrong? Is there anything I did not configure properly?

Thanks in advance. Regards, Javier

Edit:

I switched to software NSS and copied the register values from a STM32CubeMX example I found online. I cannot use those libraries for this project but I would like to have the same behaviour.

The new values are:

CR1 = 0x0278

which means

CR2 = 0x1700

which means

AFRH = 0x55303500
MODER = 0xa8a1556a

which means

I am still getting the same results and the eval kit with those libraries works fine using SPI1 instead. Therefore there must be another issue that has nothing to do with the register values.

Might there be any clock issue e.g. the pins need to get some clock?

Thanks!

Upvotes: 3

Views: 1758

Answers (1)

HelpingHand
HelpingHand

Reputation: 1468

The question points to a couple of mistakes which may explain why no receive has been observed:

  1. GPIO configuration points to some wrong Alternate Functions / Modes: The question didn't state it precisely, but I assume that

    AFRH = 0x55303500
    MODER = 0xa8a1556a
    

    refers to GPIOB (otherwise, it wouldn't make sense with SPI2). This corresponds to the following pin configuration (see the Reference Manual, sec. 8.4.1, 8.4.10 and the Datasheet, Table 16):

    PB15 - Alternate Function - AF5 = [INVALID]
    PB14 - Alternate Function - AF5 = [I2C2_SDA]
    PB13 - Alternate Function - AF3 = [TSC_G6_IO3]
    PB12 - GP Input (reset state)
    PB11 - Alternate Function - AF3 = [TIM_CH4]
    PB10 - Alternate Function - AF5 = [SPI2_SCK / I2S2_CK]
    PB09 - GP Input (reset state)
    PB08 - GP Output
    PB07 - Alternate Function - (unknown which, see register AFRL)
    PB06 - GP Output
    PB05 - Alternate Function - (unknown which, see register AFRL)
    PB04 - GP Output
    PB03 - GP Output
    PB02 - Alternate Function - (unknown which, see register AFRL)
    PB01 - Alternate Function - (unknown which, see register AFRL)
    PB00 - Alternate Function - (unknown which, see register AFRL)
    

    This is obviously not what the software is required to do.

    Solution: Make sure to configure PB15=>AF0, PB14=>AF0, either PB13=>AF0 or PB10=>AF0, depending on your hardware.

    In order to avoid mistakes in doing so, you should follow the hint of @P__J__ and use speaking macros for constants assigned to MODER, AFRH etc. Using the HAL library provided by ST is a truly controversial subject among SO users, but one should really consider to use at least a header like stm32f072xb.h with macros like GPIO_AFRH_AFSEL15. If one represents all configuration register values as (bitwise) ORs of such macros, it is easier to re-check configuration against datasheets, and the famous rubber duck will directly know what an unhappy developer is talking about.

  2. Other clock activations might be missing: The question confirms that

    The register APB1ENR is also properly configured.

    This is correct (as long as bit 14 is set).

    Additionally, GPIOB must be powered, i. e., bit 18 of RCC_AHBENR must be set. See again the Reference Manual, sec. 6.4.8 and 6.4.6.

  3. GPIO pins may be in wrong mode during debugging:

    I even configured the pins as inputs and I know I could read any digital signal the master could send. With the current configuration it seems the slave receives something because the RXNE is set when the master sends data but the read value is always 0x00.

    Please note that for every GPIO pin, a unique mode is selected through the MODER register. If this is set to "Input" (0b00), the Alternate Function is disconnected and won't work with external signals.

Upvotes: 0

Related Questions