All posts

Software Framework comes to rescue: FAT32

2 min read

Embedded applications make intense use of information these days, both for reading configurations and writing logs and process' results. Developers tend to use built-in FLASH or small EEPROM memories to archive these tasks but as information gets complex, systems' features grow and programming is done in high level languages, the need of a reliable and flexible solution takes more importance. Is in this situation when embedded systems designers incorporates technologies available in personal computers, servers and mobile devices. Using mass storage devices like USB keys, USB-SATA disks and memory cards is a great solution for several problems including portability, capacity and reliability. The Atmel's AVR32 Software Framework incorporates low level drivers for SD/MMC cards, AT45DB memories and a USB mini Host driver capable of communicating with USB keys and disks. Moreover FAT12/16/32 is present as a high level API that can be connected to any low level driver. Creating a file inside a directory, and writing something inside is as simple as this Image unavailable For making use of these drivers and components the project must be configured with the following features:

  • Drivers
    • PM
    • SPI
    • USART
    • GPIO
    • INTC
  • Components
    • SD/MMC Memory Card
  • Services
    • FAT File System
    • Memory Control Access Services

Then it is necessary to set CONFIG/conf_access.h properly to activate the SD/MMC logic unit.


/*! name Activation of Logical Unit Numbers
*/
//! @{
#define LUN_0                DISABLE  //!< On-Chip Virtual Memory.
#define LUN_1                DISABLE   //!< AT45DBX Data Flash.
#define LUN_2                ENABLE  //!< SD/MMC Card over SPI.
#define LUN_3                DISABLE
#define LUN_4                DISABLE
#define LUN_5                DISABLE
#define LUN_6                DISABLE
#define LUN_7                DISABLE
#define LUN_USB              DISABLE  //!< Host Mass-Storage Memory.
//! @}

/*! name Activation of Interface Features
*/
//! @{
#define ACCESS_USB           DISABLED //!< MEM <-> USB interface.
#define ACCESS_MEM_TO_RAM    ENABLED  //!< MEM <-> RAM interface.
#define ACCESS_STREAM        DISABLED //!< Streaming MEM <-> MEM interface.
#define ACCESS_STREAM_RECORD DISABLED //!< Streaming MEM <-> MEM interface in record mode.
#define ACCESS_MEM_TO_MEM    DISABLED //!< MEM <-> MEM interface.
#define ACCESS_CODEC         DISABLED //!< Codec interface.
//! @}

And then call this SPI initialization code from your main code:


/*! brief Initializes SD/MMC resources: GPIO, SPI and SD/MMC.
 */
static void sd_mmc_resources_init(void) {
	// GPIO pins used for SD/MMC interface
	static const gpio_map_t SD_MMC_SPI_GPIO_MAP = { { SD_MMC_SPI_SCK_PIN,
			SD_MMC_SPI_SCK_FUNCTION }, // SPI Clock.
			{ SD_MMC_SPI_MISO_PIN, SD_MMC_SPI_MISO_FUNCTION }, // MISO.
			{ SD_MMC_SPI_MOSI_PIN, SD_MMC_SPI_MOSI_FUNCTION }, // MOSI.
			{ SD_MMC_SPI_NPCS_PIN, SD_MMC_SPI_NPCS_FUNCTION } // Chip Select NPCS.
	};
	// SPI options.
	spi_options_t spiOptions = {
			.reg = SD_MMC_SPI_NPCS,
			.baudrate = SD_MMC_SPI_MASTER_SPEED, // Defined in conf_sd_mmc_spi.h.
			.bits = SD_MMC_SPI_BITS, // Defined in conf_sd_mmc_spi.h.
			.spck_delay = 0, .trans_delay = 0, .stay_act = 1, .spi_mode = 0,
			.modfdis = 1 };
	// Assign I/Os to SPI.
	gpio_enable_module(SD_MMC_SPI_GPIO_MAP, sizeof(SD_MMC_SPI_GPIO_MAP)
			/ sizeof(SD_MMC_SPI_GPIO_MAP[0]));
	// Initialize as master.
	spi_initMaster(SD_MMC_SPI, &spiOptions);
	// Set SPI selection mode: variable_ps, pcs_decode, delay.
	spi_selectionMode(SD_MMC_SPI, 0, 0, 0);
	// Enable SPI module.
	spi_enable(SD_MMC_SPI);
	// Initialize SD/MMC driver with SPI clock (PBA).
	sd_mmc_spi_init(spiOptions, PBA_HZ);
}

More posts