Using the SD Card of STM32F779NI-Eval board

U

Are you in need of an additional memory larger than EEPROM? Although EEPROM is a very easy and effective way of storing data on the board, the built in EEPROM only offers only a few bytes of storage. When working with larger or more advanced projects we may need to store additional data so an external memory solution. For that reason, MicroSD card enables you to do this quickly and easily. The following library provides a simple API to read/write sectors of the attached SD card in a STM32F779NI evaluation board.

/*! @file   dev_sd.h
    @brief  

    Copyright (C) 2017 Intelligent Systems & Computer Architecture Laboratory - T.E.I Crete
    http://isca.teicrete.gr

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 2.1 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

	Date:			May 28, 2017
    Version:        1

    Design:         Io. D
    Implementation: Io. D
*/

#ifdef __cplusplus
extern "C"
{
#endif

/******************************************************************************
 * Header File Guard Symbol Start
 ******************************************************************************/

#ifndef DEV_SD_H_

/******************************************************************************
 * Definitions
 ******************************************************************************/

#define DEV_SD_H_

/******************************************************************************
 * Includes
 ******************************************************************************/

#include <Libraries/lbr_framework.h>
#include "bsp_driver_sd.h"
#include "sdmmc.h"

/******************************************************************************
 * Structures & Global Variables
 ******************************************************************************/

extern volatile uint32_t head_sector;
extern volatile uint32_t tail_sector;
extern volatile uint32_t SD_buffer_size;

/******************************************************************************
 * Static Variables
 ******************************************************************************/

/******************************************************************************
 * Public Functions
 ******************************************************************************/

extern void SD_Init();
extern int  SD_Read(uint32_t,uint8_t *,uint32_t);
extern void SD_Append(uint8_t *,uint32_t);
extern void SD_Clear();
extern void SD_Reset_Interface();

/******************************************************************************
 * Static Functions
 ******************************************************************************/

/******************************************************************************
 * Header File Guard Symbol End
 *******************************************************************************/

#endif

#ifdef __cplusplus
}
#endif
/*! @file   dev_sd.c
    @brief  

    Copyright (C) 2017 Intelligent Systems & Computer Architecture Laboratory - T.E.I Crete
    http://isca.teicrete.gr

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 2.1 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

	Date:			May 28, 2017
    Version:        1

    Design:         Io. D
    Implementation: Io. D
*/

/******************************************************************************
 * Source File Start
 ******************************************************************************/
#define SD_SECTOR_SIZE 512
/******************************************************************************
 * Includes
 ******************************************************************************/

#include "FreeRTOS.h"
#include "task.h"
#include "cmsis_os.h"

#include "dev_sd.h"

/******************************************************************************
 * Public Variables
 ******************************************************************************/

/******************************************************************************
 * Static Variables
 ******************************************************************************/

 volatile uint32_t head_sector = 0x00;
 volatile uint32_t tail_sector = 0x00;

 volatile uint8_t SD_buffer_Out[512];
 volatile uint8_t SD_buffer_In[512];
 volatile uint32_t SD_buffer_size =0x00;

/******************************************************************************
 * Public Functions
 ******************************************************************************/

void SD_Reset_Interface()
{
	MX_SDMMC1_SD_Init();
 	BSP_SD_Init();
 	MX_FATFS_Init();
}

void SD_Init()
{
	MX_SDMMC1_SD_Init();
	BSP_SD_Init();
	MX_FATFS_Init();
	memset(SD_buffer_Out,0,512);
	memset(SD_buffer_In,0,512);
	head_sector = 0;
	tail_sector = 0;
	SD_buffer_size = 0;
}

int SD_Read(uint32_t address,uint8_t *data,uint32_t size)
{
	uint32_t remaining_data = size;
	uint32_t first_sector = address / SD_SECTOR_SIZE;
	uint32_t last_sector = (address + size) % SD_SECTOR_SIZE == 0
		? ((address + size) / SD_SECTOR_SIZE) - 1
		: (address + size) / SD_SECTOR_SIZE;
	uint32_t current_sector = first_sector > tail_sector ? tail_sector : first_sector;
	uint32_t address_offset = address % SD_SECTOR_SIZE;
	uint32_t data_position = 0;

	last_sector = last_sector > tail_sector ? tail_sector : last_sector;

	for (current_sector = first_sector; current_sector < last_sector; current_sector++)
	{
		if(BSP_SD_ReadBlocks(SD_buffer_Out,current_sector,1,100)!=HAL_OK)
		{
			osDelay(10);
			SD_Reset_Interface();
			osDelay(10);
			if(BSP_SD_ReadBlocks(SD_buffer_Out,current_sector,1,100)!=HAL_OK)
			return 0;
		}
		osDelay(10);

		memmove (&data[data_position], &SD_buffer_Out[address_offset], SD_SECTOR_SIZE - address_offset);
		remaining_data = remaining_data- (SD_SECTOR_SIZE - address_offset);
		data_position += (SD_SECTOR_SIZE - address_offset);
		address_offset = 0;
	}
	if (remaining_data != 0)
	{
		if (current_sector == tail_sector)
		{
			remaining_data = (remaining_data + (address_offset)) <= SD_buffer_size
				? remaining_data
				: SD_buffer_size <= address_offset ? 0 :  SD_buffer_size - address_offset;

			memmove (&data[data_position], &SD_buffer_In[address_offset], remaining_data);
			return data_position+remaining_data;
		}
		else if(current_sector<tail_sector)
		{
			if(BSP_SD_ReadBlocks(SD_buffer_Out,last_sector,1,100)!=HAL_OK)
			{
				osDelay(10);
				SD_Reset_Interface();
				osDelay(10);
				if(BSP_SD_ReadBlocks(SD_buffer_Out,last_sector,1,100)!=HAL_OK)
					return 0;
			}
			osDelay(10);
			memmove (&data[data_position], &SD_buffer_Out[address_offset], remaining_data);
			return data_position + remaining_data;
		}
		return 0;
	}
	return data_position;
}

void SD_Append(uint8_t *data,uint32_t size)
{
	uint32_t remaining_data = size;

	if (SD_buffer_size + size < SD_SECTOR_SIZE)
	{
		memmove (&SD_buffer_In[SD_buffer_size], data, size);
		SD_buffer_size = SD_buffer_size + size;
		return;
	}

	while (remaining_data != 0)
	{
		memmove (&SD_buffer_In[SD_buffer_size], &data[size -remaining_data], SD_SECTOR_SIZE - SD_buffer_size);
		BSP_SD_WriteBlocks (SD_buffer_In, tail_sector , 1, 100);
		osDelay (10);
		remaining_data = remaining_data - (SD_SECTOR_SIZE - SD_buffer_size);
		tail_sector++;
		SD_buffer_size = 0;
		osDelay (10);

		if (remaining_data == 0) break;
		if (remaining_data < SD_SECTOR_SIZE)
		{
			memset (SD_buffer_In, 0, SD_SECTOR_SIZE);
			memmove (&SD_buffer_In[0], data + (size - remaining_data), remaining_data);
			SD_buffer_size = remaining_data;
			remaining_data = 0;
			break;
		}
	}
}

void SD_Clear()
{
	BSP_SD_Erase(0,8192);
	memset(SD_buffer_Out,0,512);
	memset(SD_buffer_In,0,512);
	head_sector = 0;
	tail_sector = 0;
	SD_buffer_size = 0;
}

/******************************************************************************
 * Static Functions
 ******************************************************************************/

/******************************************************************************
 * Source File End
 ******************************************************************************/

 

Disclaimer: The present content may not be used for training artificial intelligence or machine learning algorithms. All other uses, including search, entertainment, and commercial use, are permitted.

Categories

Tags