[STM32GENERIC] SDIO DMA

Discussions about the STM32generic core
User avatar
Pito
Posts: 1498
Joined: Sat Mar 26, 2016 3:26 pm
Location: Rapa Nui

Re: [STM32GENERIC] SDIO DMA

Post by Pito » Thu May 18, 2017 10:37 am

stevestrong wrote:Can someone please provide a binary file for black F407VE board? Then I would test it, too.
Here you are - SerialUSB, SDIO at 24MHz, Fcpu 168MHz, HW flow ctrl disabled, 4bit mode enabled, prints error numbers with function name out.
Place a file "test_in.bin" onto your Sdcard.
You have to get "test_out.bin" as the result. Double check the hashes.
SDCopy_Test.rar
(18.08 KiB) Downloaded 13 times

Code: Select all

Use a freshly formatted SD for best performance.
Type any character to start

*************************************************
Opening the read file..
Opening the write file..
Reading and Writing..
*************************************************
Done in 463 msecs
UPDATE: here is the SDIO.cpp with CID/CSD FIX and Error numbers printing. Used in above bin too.

Code: Select all

//TODO add 1bit/4bit/8bit mode selection in begin()
//TODO add pin set functions
//TODO add instance set function and constructor
//TODO test compile to all variants
// Pito 5/2017 - CID/CSD FIX and Added Error numbers printing

#include "stm32_gpio_af.h"
#include "SDIO.h"

#include "Arduino.h"

SD_HandleTypeDef hsd;
HAL_SD_CardInfoTypedef SDCardInfo;
static uint8_t m_errorCode = SD_CARD_ERROR_INIT_NOT_CALLED;
static uint32_t m_errorLine = 0;

//=============================================================================
// Error function and macro.
#define sdError(code) setSdErrorCode(code, __LINE__)
inline bool setSdErrorCode(uint8_t code, uint32_t line) {
  m_errorCode = code;
  m_errorLine = line;
  return false;  // setSdErrorCode
}

uint8_t SDIOClass::begin() {
    GPIO_InitTypeDef GPIO_InitStruct;

    __HAL_RCC_SDIO_CLK_ENABLE();

    stm32AfSDIO4BitInit(SDIO, NULL, 0, NULL, 0,
            NULL, 0, NULL, 0, NULL, 0, NULL, 0);

    hsd.Instance = SDIO;
    hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
    hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
    hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
    hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
    hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;

    hsd.Init.ClockDiv = 0;

    error = HAL_SD_Init(&hsd, &SDCardInfo);
    if (error != SD_OK) {
      Serial.print("HAL_SD_Init Error: "); Serial.println(error);
        return false;
    }

   error = HAL_SD_WideBusOperation_Config(&hsd, SDIO_BUS_WIDE_4B);

    if (error != SD_OK) {
      Serial.print("HAL_SD_WideBusOperation_Config Error: "); Serial.println(error);
        return false;
    }
    m_errorCode = SD_CARD_ERROR_NONE;
    return true;
}

uint8_t SDIOClass::readBlocks(uint32_t block, uint8_t* dst, size_t nb) {

  //static int loopn = 0;

    error = HAL_SD_ReadBlocks(&hsd, (uint32_t*)dst, (uint64_t)block * 512, 512, nb);

    //Serial.print("Loop: "); Serial.println(loopn);
    //loopn ++;

    if (error != SD_OK) {
      Serial.print("HAL_SD_ReadBlocks Error: "); Serial.println(error);
        return false;
    }

    return HAL_SD_GetStatus(&hsd) == SD_TRANSFER_OK;

}

uint8_t SDIOClass::writeBlocks(uint32_t block, const uint8_t* src, size_t nb) {
    error = HAL_SD_WriteBlocks(&hsd, (uint32_t*)src, (uint64_t)block * 512, 512, nb);

    if (error != SD_OK) {
      Serial.print("HAL_SD_WriteBlocks Error: "); Serial.println(error);
        return false;
    }

    return HAL_SD_GetStatus(&hsd) == SD_TRANSFER_OK;
}

bool SDIOClass::erase(uint32_t firstBlock, uint32_t lastBlock) {
    error = HAL_SD_Erase(&hsd, (uint64_t)firstBlock, (uint64_t)lastBlock);

    if (error != SD_OK) {
      Serial.print("HAL_SD_Erase Error: "); Serial.println(error);
        return false;
    }

    return HAL_SD_GetStatus(&hsd) == SD_TRANSFER_OK;
}

#define SWAP_UINT32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | ((x) << 24))

bool SDIOClass::readCID(void* cid) {
    uint32_t s[4];
    s[0] = SWAP_UINT32(hsd.CID[0]);
    s[1] = SWAP_UINT32(hsd.CID[1]);
    s[2] = SWAP_UINT32(hsd.CID[2]);
    s[3] = SWAP_UINT32(hsd.CID[3]);
    memcpy(cid, &s, 16);   //&SDCardInfo.SD_cid, 16);
    return true;
  }

bool SDIOClass::readCSD(void* csd) {
  uint32_t s[4];
  s[0] = SWAP_UINT32(hsd.CSD[0]);
  s[1] = SWAP_UINT32(hsd.CSD[1]);
  s[2] = SWAP_UINT32(hsd.CSD[2]);
  s[3] = SWAP_UINT32(hsd.CSD[3]);
  memcpy(csd, &s, 16);    //&SDCardInfo.SD_csd, 16);
  return true;
}

uint32_t SDIOClass::cardSize() {
return	(SDCardInfo.CardCapacity / SDCardInfo.CardBlockSize);

}

uint8_t SDIOClass::errorCode() {
  return m_errorCode;
}

uint32_t SDIOClass::errorData() {
  return 0;
}

uint32_t SDIOClass::errorLine() {
  return m_errorLine;
}
UPDATE2: I've replaced the onboard SDIOsocket's decoupling capacitor C19=100nF with a 10uF (ceramic) one. No much change with Samsung CL10

Code: Select all

Use a freshly formatted SD for best performance.
Type any character to start
*************************************************
Opening the read file..
Opening the write file..
Reading and Writing..
HAL_SD_ReadBlocks Error: 2
HAL_SD_ReadBlocks Error: 3
HAL_SD_ReadBlocks Error: 3
HAL_SD_ReadBlocks Error: 3
...
SDsocket Black F407ZET.JPG
SDsocket Black F407ZET.JPG (23.66 KiB) Viewed 184 times
Pukao Hats Cleaning Services Ltd.

victor_pv
Posts: 1599
Joined: Mon Apr 27, 2015 12:12 pm

Re: [STM32GENERIC] SDIO DMA

Post by victor_pv » Thu May 18, 2017 2:08 pm

Error 2 is a CRC one.
The error codes are defined as HAL_SD_ErrorTypedef, which is in f4xx_hal_sd.h

I have been doing some testing, but bench doesn't fail on me.
Now, I have been going thru the HAL calls to see what checks and timeouts are there.

Once the DMA transfer has started, the next thing is wait on this to return ok or an error: HAL_SD_CheckWriteOperation
On that function the valid outcomes are a timeout, an error, or OK. I suspect the timeouts are probably reported by that one.
The one called before that, so start the DMA, may error out before starting the actual transfer if the card is not in a valid state for it.

So I suspect when a transfer goes wrong because it takes too long or something, you may be getting the timeout, and next the illegal command.

I have run the bench a bunch of times, but it just doesn't fail with my cl4 card, so I can't see where any error comes from. I need to find a cl10 so I can repeat the tests.

The new test sketch from Pito should help. I will post my current code to github so we are all in sync for a start.

Regarding the HAL updates. The core F4 HAL is from 2016. The new HAL from April 2017 has a lot of changes. Different functions, function names, returns. There must be a reason for such major changes. Most likely will result in breaking compatibility with the F1 or others that have not been updated in a while, but if we need to write 2 libraries to get them stable, then better than a single one with issues.

I have some F3 chips waiting for bluepills to arrive to do a transplant, once done I can test F3.
Last edited by victor_pv on Thu May 18, 2017 2:11 pm, edited 1 time in total.

User avatar
Pito
Posts: 1498
Joined: Sat Mar 26, 2016 3:26 pm
Location: Rapa Nui

Re: [STM32GENERIC] SDIO DMA

Post by Pito » Thu May 18, 2017 2:11 pm

Do we use DMA? Based on the Copy results it seems to me we do not (doubling the clock results in 1.6x only).
Last edited by Pito on Thu May 18, 2017 2:12 pm, edited 1 time in total.
Pukao Hats Cleaning Services Ltd.

victor_pv
Posts: 1599
Joined: Mon Apr 27, 2015 12:12 pm

Re: [STM32GENERIC] SDIO DMA

Post by victor_pv » Thu May 18, 2017 2:12 pm

Pito wrote:Do we use DMA? Based on the Copy results it seems to me we do not.
We do, performance is only slightly better than without DMA.

User avatar
Pito
Posts: 1498
Joined: Sat Mar 26, 2016 3:26 pm
Location: Rapa Nui

Re: [STM32GENERIC] SDIO DMA

Post by Pito » Thu May 18, 2017 2:22 pm

victor_pv wrote:..
I have run the bench a bunch of times, but it just doesn't fail with my cl4 card, so I can't see where any error comes from. I need to find a cl10 so I can repeat the tests...
The bench works with CL4 here as well. The issue is visible with CL10, and when you work with large files and CL4.
I suspected the CL4 cards are less power hungry than the CL10 ones, so I replaced the blocking cap at the sdcard socket.
There could be an issue with CMD6 (it switches the high speed mode on with CL10+) as well. Not sure we do CMD6.
I've been looking for some timeout constants, found a single one, increased it many times without an impact.
Pukao Hats Cleaning Services Ltd.

victor_pv
Posts: 1599
Joined: Mon Apr 27, 2015 12:12 pm

Re: [STM32GENERIC] SDIO DMA

Post by victor_pv » Thu May 18, 2017 2:26 pm

Pito wrote:
victor_pv wrote:..
I have run the bench a bunch of times, but it just doesn't fail with my cl4 card, so I can't see where any error comes from. I need to find a cl10 so I can repeat the tests...
The bench works with CL4 here as well. The issue is visible with CL10, and when you work with large files and CL4.
I suspected the CL4 cards are less power hungry than the CL10 ones, so I replaced the blocking cap at the sdcard socket.
There could be an issue with CMD6 (it switches the high speed mode on with CL10+) as well. Not sure we do CMD6.
I've been looking for some timeout constants, found a single one, increased it many times without an impact.
We dont do CMD6 at the moment, UNLESS the HAL does it for us, will need to check. But we dont do it intentionally.

I have posted a link to the latest branch in the first post for anyone willing to test, and added the bench and the copytest sketches.

danieleff
Posts: 336
Joined: Thu Sep 01, 2016 8:52 pm
Location: Hungary
Contact:

Re: [STM32GENERIC] SDIO DMA

Post by danieleff » Thu May 18, 2017 5:13 pm

victor_pv wrote: Regarding the HAL updates. The core F4 HAL is from 2016. The new HAL from April 2017 has a lot of changes. Different functions, function names, returns. There must be a reason for such major changes. Most likely will result in breaking compatibility with the F1 or others that have not been updated in a while, but if we need to write 2 libraries to get them stable, then better than a single one with issues.
You are right, F4 has differences, but only in SD card.
Created a new branch: FW-update. I checked the Release_Notes.html files, and only the F4/F7/L4 had these "HAL SD update: Overall rework of the driver for a more efficient implementation" (This might fix the problem with Pito's cards.), and the others not.
So only updated those.

It would be good if you could merge this branch to your SDIO-DMA-Latest to check the API changes. It is fine if only F1/F4 works (can be in different source files, as they will be quite different, but with the common SDIO.h). Those are the 2 different HAL APIs, the other series are similar to one or the other.

victor_pv
Posts: 1599
Joined: Mon Apr 27, 2015 12:12 pm

Re: [STM32GENERIC] SDIO DMA

Post by victor_pv » Thu May 18, 2017 6:14 pm

danieleff wrote:
victor_pv wrote: Regarding the HAL updates. The core F4 HAL is from 2016. The new HAL from April 2017 has a lot of changes. Different functions, function names, returns. There must be a reason for such major changes. Most likely will result in breaking compatibility with the F1 or others that have not been updated in a while, but if we need to write 2 libraries to get them stable, then better than a single one with issues.
You are right, F4 has differences, but only in SD card.
Created a new branch: FW-update. I checked the Release_Notes.html files, and only the F4/F7/L4 had these "HAL SD update: Overall rework of the driver for a more efficient implementation" (This might fix the problem with Pito's cards.), and the others not.
So only updated those.

It would be good if you could merge this branch to your SDIO-DMA-Latest to check the API changes. It is fine if only F1/F4 works (can be in different source files, as they will be quite different, but with the common SDIO.h). Those are the 2 different HAL APIs, the other series are similar to one or the other.
Thanks Daniel, I'll try to check that one out and start adapting the SDIO for it. Hopefully STM plans to move all the series to the same API, the F1 HAL has not been updated in a while, so perhaps the next update includes that, and we can move to a single SDIO library.
At the moment then I'll start adapting the SDIO for that new one and see if it helps with the problems.

So we may end up with 1 SDIO.h, and 2 SDIO.c ( SDIO_F1F3.., SDIO_F4L4... like you started doing). Hopefully we will still find some solution for the older HALs, to get some reliability if not speed.

victor_pv
Posts: 1599
Joined: Mon Apr 27, 2015 12:12 pm

Re: [STM32GENERIC] SDIO DMA

Post by victor_pv » Thu May 18, 2017 6:23 pm

Pito wrote:
victor_pv wrote:..
I have run the bench a bunch of times, but it just doesn't fail with my cl4 card, so I can't see where any error comes from. I need to find a cl10 so I can repeat the tests...
The bench works with CL4 here as well. The issue is visible with CL10, and when you work with large files and CL4.
I suspected the CL4 cards are less power hungry than the CL10 ones, so I replaced the blocking cap at the sdcard socket.
There could be an issue with CMD6 (it switches the high speed mode on with CL10+) as well. Not sure we do CMD6.
I've been looking for some timeout constants, found a single one, increased it many times without an impact.
There was one thing that Bill was checking for in his DMA, and we were not. DMA uses word reads and writes to memory, so the memory pointer must point to an word aligned address. I already had been thinking about that, and went and checked his code and saw he was already doing it, so I did the same check to our code.
With one difference, Bill just uses normal FIFO mode if the address is not aligned. In my latest code I make the driver hang in a loop instead because I want to catch it rather than just send without DMA, just to see if that's part of our issues.

We have 2 possible solutions for that:
Write/Read without DMA. Doesn't require alignment but would result in lower speed.
For F4 and other series with a DMA FIFO, we can do reads and writes from memory in bytes, and translate that to reads and writes to the peripheral in words, so we can reconfigure the DMA settings and use a byte aligned buffer. The bad effect is that would multiply the memory access by 4 vs word access to memory. Still better that than corruption.
The F1 doesn't have a DMA FIFO that can pack and unpack words. We can do bytes in one said and words in the other, but will not read 4 bytes to write a word, instead it will read a byte and replicate it 4 times in a word. Same when going from word to byte, will not really split a word in 4 bytes, but instead take the lower byte of the word and write that, so would cause corruption.
Since it seems like we need to split the code between F1 and F4 anyway, having different DMA configurations will not be a big deal anyway.

stevestrong
Posts: 1502
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: [STM32GENERIC] SDIO DMA

Post by stevestrong » Fri May 19, 2017 12:46 pm

Just found it on the net, maybe this helps somehow:
https://blog.frankvh.com/2011/09/04/stm ... interface/

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest