cancel
Showing results for 
Search instead for 
Did you mean: 

STM32WB55 FATFS sd real time

Lep
Senior

The stm32wb55 writes data to the sd card in real time through FATFS, and the function f_write() will take tens of ms. I want to use two buffers, one buffer to store data, and one buffer to write data to and from the sd card (can this avoid the delay of f_write?). How should I write the program?

9 REPLIES 9
AScha.3
Chief

>writes data to the sd card in real time

no.

access SDcard is minimum 1ms + data transfer time , on read. on write maybe 100ms delay...

+ data transfer time depends on setting port speed/1/4bit mode + real card speed + data size

If you feel a post has answered your question, please click "Accept as Solution".

Thank you for your help, if I collect data continuously (1mSPS), there must be missing data. That is to say, FATFS cannot store data in real time.

AScha.3
Chief

right, at 1 MSPS (i think you want Mega - not milli ?? ) and 100ms delay on write, you need buffering > 100 KB (if 8b sampels, if 16 bit -> 200KB minimum !

and to get "real time" , = continuos data stream , need 2 buffers (circular , maybe DMA mode )

and high quality sdcard, cheap may do 200ms delay sometimes 🙂

If you feel a post has answered your question, please click "Accept as Solution".

Thanks again. It's "k", sorry I made a typo. Originally, I wanted two buffers, one for storing data and one for writing to the SD card, simultaneously. I found out that it's not possible to do concurrently because stm32 is single threaded...

AScha.3
Chief

single threaded is no problem, you have DMA with about 100 channels, so fixed transfers are done by another "cpu", the dma.

and 1ksmps --- no problem . 🙂 (1000x slower than before..)

so data coming from ? adc ? anyway, set up circular dma , maybe 2x16KB , then on callback (enable callbacks for ..adc.. dma in hal /Cube ) half or full -> write 16K to sdcard, (while dma writing to other half buffer) and on next callback write next16K to sdcard ;

no gap, no stress, and good time for sdcard to write (1ksmps * 16K -> > 8 sec buffer )

If you feel a post has answered your question, please click "Accept as Solution".

Thanks again😁 . The data comes from ads1299. I use the spi driver (spi mode, no dma) of adafruit shield in the example of stm32wb55. After I add dma, it does not work (spi is ok). It should be a problem with my dma configuration. Is there any example that can make it Shall I take a look?

dma configuration

static void SPIx_Init(void)
{
  if(HAL_SPI_GetState(&hnucleo_Spi) == HAL_SPI_STATE_RESET)
  {
    /* SPI Config */
    hnucleo_Spi.Instance = NUCLEO_SPIx;
      /* SPI baudrate is set to 8 MHz maximum (PCLK2/SPI_BaudRatePrescaler = 32/4 = 8 MHz) 
       to verify these constraints:
          - ST7735 LCD SPI interface max baudrate is 15MHz for write and 6.66MHz for read
            Since the provided driver doesn't use read capability from LCD, only constraint 
            on write baudrate is considered.
          - SD card SPI interface max baudrate is 25MHz for write/read
          - PCLK2 max frequency is 32 MHz 
       */
    hnucleo_Spi.Init.BaudRatePrescaler  = SPI_BAUDRATEPRESCALER_4;
    hnucleo_Spi.Init.Direction          = SPI_DIRECTION_2LINES;
    hnucleo_Spi.Init.CLKPhase           = SPI_PHASE_2EDGE;
    hnucleo_Spi.Init.CLKPolarity        = SPI_POLARITY_HIGH;
    hnucleo_Spi.Init.CRCCalculation     = SPI_CRCCALCULATION_DISABLE;
    hnucleo_Spi.Init.CRCPolynomial      = 7;
    hnucleo_Spi.Init.CRCLength          = SPI_CRC_LENGTH_DATASIZE;
    hnucleo_Spi.Init.DataSize           = SPI_DATASIZE_8BIT;
    hnucleo_Spi.Init.FirstBit           = SPI_FIRSTBIT_MSB;
    hnucleo_Spi.Init.NSS                = SPI_NSS_SOFT;
    hnucleo_Spi.Init.NSSPMode           = SPI_NSS_PULSE_DISABLE;
    hnucleo_Spi.Init.TIMode             = SPI_TIMODE_DISABLE;
    hnucleo_Spi.Init.Mode               = SPI_MODE_MASTER;
    
    SPIx_MspInit();
    HAL_SPI_Init(&hnucleo_Spi);
 
    hdma_spi1_tx.Instance = DMA1_Channel1;
    hdma_spi1_tx.Init.Request = DMA_REQUEST_SPI1_TX;
    hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi1_tx.Init.Mode = DMA_CIRCULAR;
    hdma_spi1_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
    if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
    {
    Error_Handler();
    }
 
    __HAL_LINKDMA(&hnucleo_Spi,hdmatx,hdma_spi1_tx);
 
    /* SPI1_RX Init */
    hdma_spi1_rx.Instance = DMA1_Channel2;
    hdma_spi1_rx.Init.Request = DMA_REQUEST_SPI1_RX;
    hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi1_rx.Init.Mode = DMA_CIRCULAR;
    hdma_spi1_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
    if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
    {
     Error_Handler();
     }
 
     __HAL_LINKDMA(&hnucleo_Spi,hdmarx,hdma_spi1_rx);
  }
}
 
static void MX_DMA_Init(void)
{
 
  /* DMA controller clock enable */
  __HAL_RCC_DMAMUX1_CLK_ENABLE();
  __HAL_RCC_DMA1_CLK_ENABLE();
 
  /* DMA interrupt init */
  /* DMA1_Channel1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
  /* DMA1_Channel2_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
  /* DMAMUX1_OVR_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMAMUX1_OVR_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMAMUX1_OVR_IRQn);
 
}

​interrupt configuration

void DMA1_Channel1_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
 
  /* USER CODE END DMA1_Channel1_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_spi1_tx);
  /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
 
  /* USER CODE END DMA1_Channel1_IRQn 1 */
}
 
/**
  * @brief This function handles DMA1 channel2 global interrupt.
  */
void DMA1_Channel2_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel2_IRQn 0 */
 
  /* USER CODE END DMA1_Channel2_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_spi1_rx);
  /* USER CODE BEGIN DMA1_Channel2_IRQn 1 */
 
  /* USER CODE END DMA1_Channel2_IRQn 1 */
}

write data function 0693W00000WKmOYQA1.png(about fatfs driver)

Javier1
Principal

Ive had this issues with FATFS also, and its non deterministic long active waits between SPI communications.

It would be good if you come back once you get it working.

AScha.3
Chief

in spix_write : data is not set ! should be "1" , not pointer. right ?

If you feel a post has answered your question, please click "Accept as Solution".

Thanks again. I just use SPIx_ReadWriteData() in my sd driver.😂