SD on MCI interface with DMA HowTo

Go To Last Post
2 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

As some members requested here is a quick guide on how to make the SD_MMC_MCI ASF drivers to use the DMACA:

1. In "conf_acces.h" make sure this define is written the following way:

#define Lun_3_mem_2_ram                         sd_mmc_mci_multiple_mem_2_ram_0

The "_0" and the end of the line means your are using the MCI slot number 0, if your card is connected to the other slot, write a "_1" instead.

2.Inside "sd_mmc_mci_mem.c", change the function "sd_mmc_mci_multiple_mem_2_ram_0" this way:

Ctrl_status sd_mmc_mci_multiple_mem_2_ram_0(U32 addr, void *ram, U32 nb_sectors)
{
  return sd_mmc_mci_dma_multiple_mem_2_ram(0, addr, ram, nb_sectors);
}

3. The files "ctrl_access.c" and "ctrl_acces.h" require more changes, so I am attaching those instead of writing the instructions here. Use WinMerge or something similar to compare this files with the ASF original versions.

4. For the File system to use the multiple block read functions, "file.c" needs some changes, specifically the routine "file_read_buf" (That's what I use to read data from files). This function works faster when reading multiples of 512 bytes (1 sector). The file "fat.c" also needs some changes in the routine "fat_cache_read_sector"... Both files are also attached.

5. Finally, the point of using the DMA is to offload the processor and make it available for other tasks, so, freeRTOS should be used in the project. Your read sectors function in "sd_mmc_mci.c" should look like this:

Quote:

Bool sd_mmc_mci_dma_read_multiple_sector_2_ram(U8 slot, void *ram, U32 nb_sector)
{
int *pRam = ram;

// Src Address: the MCI registers.
AVR32_DMACA.sar1 = (U32)&AVR32_MCI.fifo;

// Dst Address: the OutputData[] array.
AVR32_DMACA.dar1 = (unsigned long)pRam;

// Channel 1 Ctrl register high
AVR32_DMACA.ctl1h =
( (nb_sector*(SD_MMC_SECTOR_SIZE/4)) << AVR32_DMACA_CTL1H_BLOCK_TS_OFFSET) // Block transfer size
;

// Enable Channel 1 : start the process.
AVR32_DMACA.chenreg = ((2<<AVR32_DMACA_CHENREG_CH_EN_OFFSET) | (2<<AVR32_DMACA_CHENREG_CH_EN_WE_OFFSET));

// Wait for the end of the AES->RAM transfer (channel 1).
while(AVR32_DMACA.chenreg & (2<<AVR32_DMACA_CHENREG_CH_EN_OFFSET)){
vTaskDelay (2 / portTICK_RATE_MS);
}

return TRUE;
}

Perhaps interrupts and a semaphore take could be used instead of the delay, but since this was enough for my needs I didn't look into the DMACA interrupts settings.

One more thing, the above changes are only for reading, if you also want to write multiple sectors using the DMA, the changes are very similar, and the file write routine to use (and to modify accordingly) is "file_write_buf".

I hope everything is clear, let me know in case is not.

Attachment(s): 

Daniel Campora http://www.wipy.io

Last Edited: Tue. Jan 24, 2012 - 07:58 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am attaching "fat.c" here since there seems to be a maximum per post.

Attachment(s): 

Daniel Campora http://www.wipy.io