saukijan
saukijan

Reputation: 23

STM32 discovery F3 SPI loopback RXFIFO receives no data

I am working with STM32 F3 discovery kit and started messing with SPI peripheral. I started with a simple loop-back system: I check the TXFIFOLVL status and if it is not full I send my data to DR register, which then should loop back to my RxBuffer (I read data from DR while RXFIFOLVL is not empty), but I've hit a problem - I don't get anything back on my receiving buffer and I can't seem to see why. I don't use HAL or Standard Peripheral Library, so I configure the SPI and use it via the register values like this:

Header file for SPI code:

#define GPIOA_ENABLE                    0b1<<17             // Enable GPIO port A clock in AHBENR register
#define SPI1_CLOCK_ENABLE               0b1<<12             // Enable SPI1 clock in APB2ENR register
#define SPI1_PIN_ALT_FNC                0b1010<<4           // Sets PA5,PA6 & PA7 to Alternative function
#define SPI1_OUTPUT_TYPE                ~(0b111<<5)         // Sets PA5, PA6 & PA7 to push-pull
#define SPI1_PIN_SPEED                  0b1111<<4           // Sets pins from 4 to 7 to work on 50 MHz output speed
#define SPI1_PIN_ALT_FNC_LOW            0b0101<<4           // Sets the Alternative function to AF5 in alternative function low register
#define SPI1_PIN_ALT_FNC_HIGH           0b0101<<4           // Sets the Alternative function to AF5 in alternative function high register
#define SPI1_BAUDRATE_PRESCALER_2       0b000<<3            // F_PCLK/2
#define SPI1_BAUDRATE_PRESCALER_128     0b110<<3            // F_PCLK/128
#define SPI1_MASTER_MODE                0b1<<2              // Sets the SPI1 to master mode
#define SPI1_PERI_ENABLE                0b1<<6              // Enable the SPI peripheral
#define SPI1_SSM_ENABLE                 0b1<<9              // Enable SPI software slave management
#define SPI1_SSI_ENABLE                 0b1<<8              // SPI1 internal slave select
#define SPI1_NSSP_ENABLE                0b1<<3              // Enable NSS pulse management
#define SPI1_FRXTH_8BIT                 0b1<<12             //Set the FIFO reception threshold to 8 bits
#define SPI1_DATA_SIZE                  0b0111<<8           // SPI1 DATA size
#define SPI1_TXFIFO_FULL_FLAG           0b11<<11            // SPI1 Tx FIFO transmission flag
#define SPI1_RXFIFO_EMPTY_FLAG          0b00<<9             // SPI1 Rx FIFO reception flag

#include "main.h"
#include "stm32f3xx_hal.h"

void spi_init();
void spi_WriteRead(uint8_t *rxBuffer, uint8_t *txBuffer, uint8_t bufferSize);

Code file for SPI code:

#include "SPI_toSD.h"

/* SPI1 configuration
 * PA5 - SCK
 * PA6 - MISO
 * PA7 - MOSI
 */
void spi_init(){

// Start the GPIO and peripheral clocks in Reset and Clock Control register
RCC->AHBENR |= GPIOA_ENABLE;
RCC->APB2ENR |= SPI1_CLOCK_ENABLE;

// Configure the GPIOs for SPI communication
GPIOA->MODER |= SPI1_PIN_ALT_FNC;
GPIOA->OTYPER &= SPI1_OUTPUT_TYPE;
GPIOA->OSPEEDR |= SPI1_PIN_SPEED;
GPIOA->AFR[0] |= SPI1_PIN_ALT_FNC_LOW;
GPIOA->AFR[1] |= SPI1_PIN_ALT_FNC_HIGH;

// Configure the SPI peripheral
SPI1->CR1 |= SPI1_BAUDRATE_PRESCALER_2;
SPI1->CR1 |= SPI1_SSM_ENABLE;
SPI1->CR1 |= SPI1_MASTER_MODE;
SPI1->CR1 |= SPI1_SSI_ENABLE;
SPI1->CR2 |= SPI1_DATA_SIZE;
SPI1->CR2 |= SPI1_FRXTH_8BIT;
SPI1->CR2 |= SPI1_NSSP_ENABLE;
SPI1->CR1 |= SPI1_PERI_ENABLE;
SPI1->CR1 &= ~SPI1_SSI_ENABLE;

}

void spi_WriteRead(uint8_t *rxBuffer, uint8_t *txBuffer, uint8_t bufferSize){
int i;
while((SPI1->SR & 0b11<<11)==SPI1_TXFIFO_FULL_FLAG);
for(i=0;i<bufferSize;i++){
        SPI1->DR |= *txBuffer;  // send *txBuffer++
        txBuffer++;


    while((SPI1->SR & 0b11<<9)!=SPI1_RXFIFO_EMPTY_FLAG){
        *rxBuffer = SPI1->DR;
        rxBuffer++;
    }
}

}

In main I simply define my buffers and initialize them like this:

uint8_t rx_buff[SIZE] = {0,0,0,0,0,0,0,0,0,0};
uint8_t tx_buff[SIZE] = {1,2,3,4,5,6,7,8,9,10};

So naturally after my spi_WriteRead() function is called I expect these buffers to have the same values.

I call my spi_init() function and in my while loop I call spi_WriteRead() function:

  spi_WriteRead(rx_buff,tx_buff,SIZE);

SIZE is defined in my main.c as:

#define SIZE  10

I use SW4STM32 environment to code and debug so in my debugger I can see all of the register values. My SPI is initialized just as I defined and my data is being sent to TXFIFO buffer, but nothing comes to RXFIFO buffer. If I check SPI SR register I can see that my TXFIFO fills up, but RXFIFO flags say that it is empty.

Does anyone have any clue what I might be doing wrong? Am I grossly misunderstanding something simple about SPI? Thanks for your input!

Upvotes: 2

Views: 979

Answers (1)

Freddie Chopin
Freddie Chopin

Reputation: 8860

EDIT:

Take a good look here:

#define SPI1_SSI_ENABLE                 0b1<<8
...
SPI1->CR1 |= SPI1_PERI_ENABLE;
SPI1->CR1 &= ~SPI1_SSI_ENABLE;

Now you'll probably know why #define macros are generally considered a bad idea. You wouldn't have this problem if you'd use #define values from stm32f3xxx.h header, as all values with operations have parentheses there. You don't have them. That's why your code looks like this for the compiler:

SPI1->CR1 |= SPI1_PERI_ENABLE;
SPI1->CR1 &= ~0b1<<8;

Which is equivalent to:

SPI1->CR1 |= SPI1_PERI_ENABLE;
SPI1->CR1 &= (~0b1)<<8;

And going further:

SPI1->CR1 |= SPI1_PERI_ENABLE;
SPI1->CR1 &= 0xffffff00;

Probably not what you wanted.

You should also know, that if your device is a master, then SSI and SSM bits should both be set. https://stackoverflow.com/a/42169600/157344

ORIGINAL:

Do note, that in these devices when you access SPI1->DR directly you send/receive TWO bytes at once. That's because this register is defined as uint16_t and SPI supports so called "Data packing" (search for it in the Reference Manual). If you want to send/receive one byte at a time, then you need to cast the register for write and read like that:

readByte = (volatile uint8_t*)SPI1->DR;
(volatile uint8_t*)SPI1->DR = writeByte;

BTW - why don't you use #defines provided by the CMSIS headers? You wouldn't have to define things like SPI1_MASTER_MODE...

Upvotes: 2

Related Questions