cancel
Showing results for 
Search instead for 
Did you mean: 

SPI recieve over DMA works only once in stm32f103 on HAL

Vthe
Associate II

Hello. I'm trying to receive data from W25Q128 via SPI. It works good, but too slow, if I don't use DMA. If I'm using DMA, it works faster, but only once, second query doesn't return data.

I'm reading flash in main loop once in second this way, when don't use DMA:

while (1)
  {
      if (flag)
      {
         diff = mks_counter;
         flashReadFromAddress(flash1, address, 512, sd_buff);
         diff = mks_counter - diff;
         // Send time diff
         HAL_UART_Transmit(&huart1, (uint8_t *)&diff, 8, 100);
         HAL_Delay(100);
         // Send 8 bytes of recieved data
         HAL_UART_Transmit(&huart1, sd_buff, 8, 100);
         address+= 512;
         flag = 0;
      }
  }

Flash read function looks like this:

void flashReadFromAddress(W25Flash_HandleTypeDef flash, uint32_t address, uint16_t byteCount, uint8_t * buff)
{
   uint8_t command;
 
   flashSelectChip(flash);
 
   command = W25_COMMAND_FAST_READ;
   HAL_SPI_Transmit(&flash.spi, &command, 1, 10);
 
   command = (address & 0xFF0000) >> 16;
   HAL_SPI_Transmit(&flash.spi, &command, 1, 10);
 
   command = (address & 0xFF00) >> 8;
   HAL_SPI_Transmit(&flash.spi, &command, 1, 10);
 
   command = address & 0xFF;
   HAL_SPI_Transmit(&flash.spi, &command, 1, 10);
 
   command = 0x00;
   HAL_SPI_Transmit(&flash.spi, &command, 1, 10);
   
   HAL_SPI_Receive(&flash.spi, buff, byteCount, 100);
   
   flashDeselectChip(flash);
}

I'm reading flash in main loop once in second this way, when use DMA:

while (1)
  {
      if (flag)
      {
         diff = mks_counter;
         HAL_StatusTypeDef result = flashReadFromAddressDMA(&flash1, address, 512, sd_buff);
         // Wait, while data is receiving
         while(flash1.isReceiving == 1);
         diff = mks_counter - diff;
         xprintf("Rst: %d\n", result);
         // Send time diff
         HAL_UART_Transmit(&huart1, (uint8_t *)&diff, 8, 100);
         HAL_Delay(100);
         // Send 8 bytes of received data
         HAL_UART_Transmit(&huart1, sd_buff, 8, 100);
         address+= 512;
         flag = 0;
      }
  }
}

Flash read function looks like this for this case:

HAL_StatusTypeDef flashReadFromAddressDMA(W25Flash_HandleTypeDef * flash, uint32_t address, uint16_t byteCount, uint8_t * buff)
{
   flash->isReceiving = 1;
 
   uint8_t command;
 
   flashSelectChip(*flash);
 
   command = W25_COMMAND_FAST_READ;
   HAL_SPI_Transmit(&flash->spi, &command, 1, 10);
 
   command = (address & 0xFF0000) >> 16;
   HAL_SPI_Transmit(&flash->spi, &command, 1, 10);
 
   command = (address & 0xFF00) >> 8;
   HAL_SPI_Transmit(&flash->spi, &command, 1, 10);
 
   command = address & 0xFF;
   HAL_SPI_Transmit(&flash->spi, &command, 1, 10);
 
   command = 0x00;
   HAL_SPI_Transmit(&flash->spi, &command, 1, 10);
   
   HAL_StatusTypeDef result = HAL_SPI_Receive_DMA(&flash->spi, buff, byteCount);
 
   return result;
}

Finish of reading is determining in callback:

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
   flash1.isReceiving = 0;
   flashDeselectChip(flash1);
}

So, when I don't use DMA, I recieve proper new data for each iteration:

0690X00000AQVGCQA5.jpg

When I'm using DMA, I'm receiving proper data for first iteration, and data either stay the same for next iterations, or, after some iterations became 0xFF or 0x00 (but, when debugging, breakpoint in callback is triggered on each iteration).

0690X00000AQVOVQA5.jpg

DMA is enabled both for SPI send and SPI receive, for both autoincrement is memory, data size is byte, bufer type is normal. Could I change this behavior for DMA receiving? Or could I up speed somehow without DMA? My results is:

0690X00000AQVWeQAP.jpg

0 REPLIES 0