AnsweredAssumed Answered

STM32F4DIS-BB FatFs

Question asked by b.dean on Jul 14, 2017
Latest reply on Mar 26, 2018 by Clive One

My kit is the STM32F4 Discovery board and the STM32F4BB-DIS expansion board. My OS is Linux Ubuntu 16.04 LTS. I have been trying for some time to get one of the third party demo programs that was listed from ST to work. In particular I am struggling to get the FatFs program from Embest to work. I managed to get the uSDCard program operational which allows one to low level R/W blocks onto the uSDCard (2Gb), but as of yet no success with the FatFs. The FatFs program was meant to demonstrate how to use the SDIO firmware library and an associated driver to implent Fatfs onto the SD card. As for the details on how the program is meant to work I will list it below along with the main program that I am using. Aside from not knowing where I am falling short I have a question outside of this once I get this program to work. How might I approach the recording of video onto a uSDCard and in particular what file format might one suggest? I understand that 2Gb is rather limited nonetheless I would like to explore this further. At any rate first things first what am I missing in my program?

 

Below is what the program is suppose to do and although my make file compiles error free I am obviously missing something here as when I go to use gtkterm and my hyperterminal with the correct settings and configuration it does not work. I even went so far as to enlist another guys post and had even less success there.

 

http://thehackerworkshop.com/?p=1103

 

 

 

1. Description

The example is located in the following folder:

\Codes\STM32F4xx_SDIO_Example\Project\FatFs

2. Hardware Configuration

A MicroSD card is needed in this example and Kingston 1GB/2GB or SanDisk 2GB

MicroSD Card is recommended. The card should be formatted before used.

Note: Kingston 1GB/2GB and SanDisk 2GB MicroSD Card have been tested on

DevKit407. It’s not guaranteed that all kind of MicroSD card work well on the board.

3. Software Configuration

HyperTerminal is used in this example. Please refer 3.3.1 HyperTerminal Connection to

for more details.

4. Steps to Run

STM32F4DIS-BB

User Manual

Embest Technology Co., LTD

Page 36 of 901)

Connect a null-modem female/female RS232 cable between the DB9 connector

COM1 (USART6) and PC serial port.

2) Make sure that jumpers JP1 and JP2 are fitted.

3) Open hyperterminal on PC.

4) Copy message.txt in the project folder to a MicroSD card.

5) Insert the MicroSD card into MicroSD slot CON6.

6) Connect the DevKit407 board to a PC with a ‘USB type A (Male) to Mini-B (Male)’

cable through USB connector CN1 to power the board.

7) Open the project, rebuild all files, load project image and then run program.

8) Testing actions and results:

After reset, then see the serial terminal, it should be like this:

Debug Module Init

Open a test file (message.txt)

Type the file content

hello world!

Close the file

Create a new file (hello.txt)

Write a text data. (hello.txt)

14 bytes written

Close the file

read the file (hello.txt)

Type the file content(hello.txt)

Hello world!

Close the file (hello.txt)

Open root directory

Directory listing...

14 HELLO.TXT

12 MESSAGE.TXT

STM32F4DIS-BB

User Manual

Embest Technology Co., LTD

Page 37 of 90Test completed

4.2.2 uSDCard

1. Description

The example is located in the following folder:

\Codes\STM32F4xx_SDIO_Example\Project\uSDCard

2. Hardware Configuration

A MicroSD card is needed in this example and Kingston 1GB/2GB or SanDisk 2GB

MicroSD Card is recommended. The card should be formatted before used.

Note: Kingston 1GB/2GB and SanDisk 2GB MicroSD Card have been tested on

DevKit407. It’s not guaranteed that all kind of MicroSD card work well on the board.

3. Steps to Run

1) Insert the MicroSD card into MicroSD slot CON6.

2) Connect the DevKit407 board to a PC with a ‘USB type A (Male) to Mini-B (Male)’

cable through USB connector CN1 to power the board.

3) Open the project, rebuild all files, load project image and then run program.

4) Testing actions and results:

If the Erase operation is PASSED then LED3 ON else the LED6 is ON and LED3

is OFF

If the Single Block Write/Read operation is PASSED then LED4 ON else the

LED6 is ON and LED4 is OFF

If the Multi Blocks Write/Read operation is PASSED then LED5 ON else the

LED6 is ON and LED5 is OFF

Any SD Card operation including the SD Initialization error is signaled by LED6

ON.

STM32F4DIS-BB

User Manual

Embest

 

And here is my program ...

 

/**

******************************************************************************

* <h2><center>&copy; COPYRIGHT 2012 Embest Tech. Co., Ltd.</center></h2>

* @file main.c

* @author CMP Team

* @version V1.0.0

* @date 28-December-2012

* @brief This example provides a example of how to use the SDIO firmware library

* and an associate driver to implement Fatfs on the SD Card memory.

******************************************************************************

* @attention

*

* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS

* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE

* TIME. AS A RESULT, Embest SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT

* OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT

* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION

* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.

******************************************************************************

*/

/* Includes ------------------------------------------------------------------*/

#include <stdio.h>

#include "../inc/main.h"

#include "../lib/CMSIS/include/stm32f4xx.h"

#include "../lib/STM32F4-Discovery/stm32f4_discovery.h"

#include "../lib/STM32F4-Discovery/stm32f4_discovery_sdio_sd.h"

#include "../lib/STM32F4-Discovery/stm32f4_discovery_debug.h"

#include "../lib/FatFs_vR0.08a/ff.h"

#include "../inc/system_stm32f4xx.h"

#include "../lib/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_usart.h"

#include "../inc/logf.h"

#include "../lib/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_gpio.h"

 

//#include "../inc/sdio_high_level.h"

// there is a duplication with sdio_high_level.h at line 33 (i.e. line above) which ripples through to the lib at stm32f4_discovery_sdio_sd.h. When I comment this line

// out I am down to one error

//#include "simplesdio.h"

//#include "logf.h"

 

/* Private typedef -----------------------------------------------------------*/

typedef enum {

FAILED = 0, PASSED = !FAILED

} TestStatus;

 

/* Private define ------------------------------------------------------------*/

#define BLOCK_SIZE 512 /* Block Size in Bytes */

 

#define NUMBER_OF_BLOCKS 100 /* For Multi Blocks operation (Read/Write) */

#define MULTI_BUFFER_SIZE (BLOCK_SIZE * NUMBER_OF_BLOCKS)

 

#define SD_OPERATION_ERASE 0

#define SD_OPERATION_BLOCK 1

#define SD_OPERATION_MULTI_BLOCK 2

#define SD_OPERATION_END 3

 

/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/

uint8_t aBuffer_Block_Tx[BLOCK_SIZE];

uint8_t aBuffer_Block_Rx[BLOCK_SIZE];

uint8_t aBuffer_MultiBlock_Tx[MULTI_BUFFER_SIZE];

uint8_t aBuffer_MultiBlock_Rx[MULTI_BUFFER_SIZE];

__IO TestStatus EraseStatus = FAILED;

__IO TestStatus TransferStatus1 = FAILED;

__IO TestStatus TransferStatus2 = FAILED;

 

SD_Error Status = SD_OK;

__IO uint32_t uwSDCardOperation = SD_OPERATION_BLOCK;

 

/* Private function prototypes -----------------------------------------------*/

static void NVIC_Configuration (void);

static void SD_EraseTest (void);

static void SD_SingleBlockTest (void);

static void SD_MultiBlockTest (void);

static void Fill_Buffer (uint8_t *pBuffer, uint32_t BufferLength, uint32_t Offset);

 

static TestStatus Buffercmp (uint8_t* pBuffer1, uint8_t* pBuffer2, uint32_t BufferLength);

static TestStatus eBuffercmp (uint8_t* pBuffer, uint32_t BufferLength);

 

/* Private functions ---------------------------------------------------------*/

 

/**

* @brief Configures SDIO IRQ channel.

* @param None

* @retval None

*/

static void NVIC_Configuration (void)

{

NVIC_InitTypeDef NVIC_InitStructure;

 

/* Configure the NVIC Preemption Priority Bits */

NVIC_PriorityGroupConfig (NVIC_PriorityGroup_1);

 

NVIC_InitStructure.NVIC_IRQChannel = SDIO_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init (&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = SD_SDIO_DMA_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

NVIC_Init (&NVIC_InitStructure);

}

 

/**

* @brief Tests the SD card erase operation.

* @param None

* @retval None

*/

static void SD_EraseTest (void)

{

/*------------------- Block Erase ------------------------------------------*/

if (Status == SD_OK) {

/* Erase NumberOfBlocks Blocks of WRITE_BL_LEN(512 Bytes) */

Status = SD_Erase (0x00, (BLOCK_SIZE * NUMBER_OF_BLOCKS));

}

else {

logf ("SD_EraseTest failed 1\r\n");

}

 

if (Status == SD_OK) {

logf ("SD_Erase OK, performing SD_ReadMultiBlocks\r\n");

 

Status = SD_ReadMultiBlocks (aBuffer_MultiBlock_Rx, 0x00, BLOCK_SIZE, NUMBER_OF_BLOCKS);

 

if (Status == SD_OK) {

logf ("SD_ReadMultiBlocks OK\r\n");

}

else {

logf ("SD_ReadMultiBlocks failed\r\n");

}

 

/* Check if the Transfer is finished */

Status = SD_WaitReadOperation ();

 

if (Status == SD_OK) {

logf ("SD_WaitReadOperation OK\r\n");

}

else {

logf ("SD_WaitReadOperation failed\r\n");

}

 

/* Wait until end of DMA transfer */

while (SD_GetStatus () != SD_TRANSFER_OK)

;

 

logf ("SD_TRANSFER_OK\r\n");

}

 

/* Check the correctness of erased blocks */

if (Status == SD_OK) {

EraseStatus = eBuffercmp (aBuffer_MultiBlock_Rx, MULTI_BUFFER_SIZE);

}

 

if (EraseStatus == PASSED) {

logf ("SD erase test passed\r\n");

}

else {

logf ("SD erase test failed\r\n");

}

}

 

/**

* @brief Tests the SD card Single Blocks operations.

* @param None

* @retval None

*/

static void SD_SingleBlockTest (void)

{

/*------------------- Block Read/Write --------------------------*/

/* Fill the buffer to send */

Fill_Buffer (aBuffer_Block_Tx, BLOCK_SIZE, 0x1234F);

 

if (Status == SD_OK) {

/* Write block of 512 bytes on address 0 */

Status = SD_WriteBlock (aBuffer_Block_Tx, 0x00, BLOCK_SIZE);

/* Check if the Transfer is finished */

Status = SD_WaitWriteOperation ();

while (SD_GetStatus () != SD_TRANSFER_OK)

;

}

 

if (Status == SD_OK) {

/* Read block of 512 bytes from address 0 */

Status = SD_ReadBlock (aBuffer_Block_Rx, 0x00, BLOCK_SIZE);

/* Check if the Transfer is finished */

Status = SD_WaitReadOperation ();

while (SD_GetStatus () != SD_TRANSFER_OK)

;

}

 

/* Check the correctness of written data */

if (Status == SD_OK) {

TransferStatus1 = Buffercmp (aBuffer_Block_Tx, aBuffer_Block_Rx, BLOCK_SIZE);

}

 

if (TransferStatus1 == PASSED) {

logf ("Single block test passed\r\n");

}

else {

logf ("Single block test failed\r\n");

}

}

 

/**

* @brief Tests the SD card Multiple Blocks operations.

* @param None

* @retval None

*/

static void SD_MultiBlockTest (void)

{

/* Fill the buffer to send */

Fill_Buffer (aBuffer_MultiBlock_Tx, MULTI_BUFFER_SIZE, 0x0);

 

if (Status == SD_OK) {

/* Write multiple block of many bytes on address 0 */

Status = SD_WriteMultiBlocks (aBuffer_MultiBlock_Tx, 0, BLOCK_SIZE, NUMBER_OF_BLOCKS);

 

/* Check if the Transfer is finished */

Status = SD_WaitWriteOperation ();

while (SD_GetStatus () != SD_TRANSFER_OK)

;

}

 

if (Status == SD_OK) {

/* Read block of many bytes from address 0 */

Status = SD_ReadMultiBlocks (aBuffer_MultiBlock_Rx, 0, BLOCK_SIZE, NUMBER_OF_BLOCKS);

 

/* Check if the Transfer is finished */

Status = SD_WaitReadOperation ();

while (SD_GetStatus () != SD_TRANSFER_OK)

;

}

 

/* Check the correctness of written data */

if (Status == SD_OK) {

TransferStatus2 = Buffercmp (aBuffer_MultiBlock_Tx, aBuffer_MultiBlock_Rx, MULTI_BUFFER_SIZE);

}

 

if (TransferStatus2 == PASSED) {

logf ("Multiple block test passed\r\n");

}

else {

logf ("Multiple block test failed\r\n");

}

}

 

/**

* @brief Compares two buffers.

* @param pBuffer1, pBuffer2: buffers to be compared.

* @param BufferLength: buffer's length

* @retval PASSED: pBuffer1 identical to pBuffer2

* FAILED: pBuffer1 differs from pBuffer2

*/

static TestStatus Buffercmp (uint8_t* pBuffer1, uint8_t* pBuffer2, uint32_t BufferLength)

{

while (BufferLength--) {

if (*pBuffer1 != *pBuffer2) {

return FAILED;

}

 

pBuffer1++;

pBuffer2++;

}

 

return PASSED;

}

 

/**

* @brief Fills buffer with user predefined data.

* @param pBuffer: pointer on the Buffer to fill

* @param BufferLength: size of the buffer to fill

* @param Offset: first value to fill on the Buffer

* @retval None

*/

static void Fill_Buffer (uint8_t *pBuffer, uint32_t BufferLength, uint32_t Offset)

{

uint16_t index = 0;

 

/* Put in global buffer same values */

for (index = 0; index < BufferLength; index++) {

pBuffer[index] = index + Offset;

}

}

 

/**

* @brief Checks if a buffer has all its values are equal to zero.

* @param pBuffer: buffer to be compared.

* @param BufferLength: buffer's length

* @retval PASSED: pBuffer values are zero

* FAILED: At least one value from pBuffer buffer is different from zero.

*/

static TestStatus eBuffercmp (uint8_t* pBuffer, uint32_t BufferLength)

{

while (BufferLength--) {

/* In some SD Cards the erased state is 0xFF, in others it's 0x00 */

if ((*pBuffer != 0xFF) && (*pBuffer != 0x00)) {

return FAILED;

}

 

pBuffer++;

}

 

return PASSED;

}

 

/**

* For printf.

*/

void initUsart (void)

{

#define USE_USART 1

#define USE_PIN_SET 1

 

#if USE_USART == 1

#define USART USART1

#define RCC_USART RCC_APB2Periph_USART1

#define RCC_APBxPeriphClockCmd RCC_APB2PeriphClockCmd

#define GPIO_AF_USART GPIO_AF_USART1

 

#if USE_PIN_SET == 1

#define RCC_GPIO RCC_AHB1Periph_GPIOB

#define PORT GPIOB

#define TX_PIN_SOURCE GPIO_PinSource6

#define RX_PIN_SOURCE GPIO_PinSource7

#define TX_PIN GPIO_Pin_6

#define RX_PIN GPIO_Pin_7

#endif

 

#if USE_PIN_SET == 2

#define RCC_GPIO RCC_AHB1Periph_GPIOA

#define PORT GPIOA

#define TX_PIN_SOURCE GPIO_PinSource9

#define RX_PIN_SOURCE GPIO_PinSource10

#define TX_PIN GPIO_Pin_9

#define RX_PIN GPIO_Pin_10

#endif

#endif

 

#if USE_USART == 2

#define USART USART2

#define RCC_USART RCC_APB1Periph_USART2

#define RCC_APBxPeriphClockCmd RCC_APB1PeriphClockCmd

#define GPIO_AF_USART GPIO_AF_USART2

 

#if USE_PIN_SET == 1

#define RCC_GPIO RCC_AHB1Periph_GPIOA

#define PORT GPIOA

#define TX_PIN_SOURCE GPIO_PinSource2

#define RX_PIN_SOURCE GPIO_PinSource3

#define TX_PIN GPIO_Pin_2

#define RX_PIN GPIO_Pin_3

#endif

 

#if USE_PIN_SET == 2

#define RCC_GPIO RCC_AHB1Periph_GPIOA

#define PORT GPIOA

#define TX_PIN_SOURCE GPIO_PinSource9

#define RX_PIN_SOURCE GPIO_PinSource10

#define TX_PIN GPIO_Pin_9

#define RX_PIN GPIO_Pin_10

#endif

#endif

 

RCC_APBxPeriphClockCmd (RCC_USART, ENABLE);

GPIO_InitTypeDef gpioInitStruct;

 

RCC_AHB1PeriphClockCmd (RCC_GPIO, ENABLE);

gpioInitStruct.GPIO_Pin = TX_PIN | RX_PIN;

gpioInitStruct.GPIO_Mode = GPIO_Mode_AF;

gpioInitStruct.GPIO_Speed = GPIO_Speed_2MHz;

gpioInitStruct.GPIO_OType = GPIO_OType_PP;

gpioInitStruct.GPIO_PuPd = GPIO_PuPd_UP;

GPIO_Init (PORT, &gpioInitStruct);

GPIO_PinAFConfig (PORT, TX_PIN_SOURCE, GPIO_AF_USART);

// TX

GPIO_PinAFConfig (PORT, RX_PIN_SOURCE, GPIO_AF_USART);

// RX

 

USART_InitTypeDef usartInitStruct;

usartInitStruct.USART_BaudRate = 9600;

usartInitStruct.USART_WordLength = USART_WordLength_8b;

usartInitStruct.USART_StopBits = USART_StopBits_1;

usartInitStruct.USART_Parity = USART_Parity_No;

usartInitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

usartInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

USART_Init (USART, &usartInitStruct);

USART_Cmd (USART, ENABLE);

}

 

int main (void)

{

initUsart ();

logf ("Init\r\n");

 

/*!< At this stage the microcontroller clock setting is already configured,

this is done through SystemInit() function which is called from startup

files (startup_stm32f40_41xxx.s/startup_stm32f427_437xx.s)

before to branch to application main. To reconfigure the default setting

of SystemInit() function, refer to system_stm32f4xx.c file

*/

 

/* NVIC Configuration */

NVIC_Configuration ();

logf ("NVIC_Configuration\r\n");

 

/*------------------------------ SD Init ---------------------------------- */

if ((Status = SD_Init ()) != SD_OK) {

logf ("SD_Init failed\r\n");

}

else {

logf ("SD_Init OK\r\n");

}

 

while ((Status == SD_OK) && (uwSDCardOperation != SD_OPERATION_END) && (SD_Detect () == SD_PRESENT)) {

switch (uwSDCardOperation) {

/*-------------------------- SD Single Block Test --------------------- */

case (SD_OPERATION_BLOCK):

{

SD_SingleBlockTest ();

uwSDCardOperation = SD_OPERATION_ERASE;

break;

}

/*-------------------------- SD Erase Test ---------------------------- */

case (SD_OPERATION_ERASE):

{

SD_EraseTest ();

uwSDCardOperation = SD_OPERATION_MULTI_BLOCK;

break;

}

/*-------------------------- SD Multi Blocks Test --------------------- */

case (SD_OPERATION_MULTI_BLOCK):

{

SD_MultiBlockTest ();

uwSDCardOperation = SD_OPERATION_END;

break;

}

}

}

 

/* Infinite loop */

while (1) {

}

}

Outcomes