Перейти к содержанию
    

STM32F4Discovery + SDIO DMA

Здравствуйте!

 

Использую Дискавери на STM32F407 + карту SD Micro 4 GB на чтение.

 

Чтение через поллинг (Polling) идет отлично, даже файлы верно читаются с помощью FatFs.

 

Но через DMA не удаётся нормально работать.

Помотрел как читается нулевой(первый сектор) карты в 2 случаях: Polling и DMA.

 

Фрагменты кода (прерывания включил, карту проинитил, данные выровнял на 16 байт) :

 

u8 buff[512] __attribute__((aligned (16)));

void SDIO_IRQHandler(void)
{
SD_ProcessIRQSrc();
}

void SD_SDIO_DMA_IRQHANDLER(void)
{
SD_ProcessDMAIRQ();
}

void SD_NVIC_Configuration(void)
{
// SDIO Interrupt ENABLE

NVIC_InitTypeDef NVIC_InitStructure;

               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);
               // DMA2 STREAMx Interrupt ENABLE
               NVIC_InitStructure.NVIC_IRQChannel = SD_SDIO_DMA_IRQn;
               NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
               NVIC_Init(&NVIC_InitStructure);
}

SD_Init();

SD_NVIC_Configuration();
__enable_irq();

SD_ReadBlock(buff,0<<9,512);

OLED_ON();

#define COL 255

for(u32 i=0;i<512;i++)OLED_Char(i%20,i/20,buff[i],COL|(COL<<8)|(COL<<16));

while(1);

 

 

Фотки прикладываю. Вывод содержимого нулевого сектора на дисплей.

 

Первая картинка - перез Polling - там всё OK.

 

Вторая через DMA - первые байты (от трети до половины всего экрана) - нулевые.

 

Куда копать, чтобы DMA нормально на чтение с SDIO начал работать?

 

post-99126-1521198324_thumb.jpg

post-99126-1521198336_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

посчитал. 112 байт не хватает в начале.

а они точно нулевые? м.б. там нечитаемые символы, отличные от 0x00 и 0xFF?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чтение секторов через DMA заработало.

 

После чтения надо ждать завершения ДМА:

 

while(DMA2_Stream3->CR&DMA_SxCR_EN);
DMA2->LIFCR=DMA_IT_TCIF3&0x0F7D0F7D;
DMA2_Stream3->CR|=DMA_SxCR_EN;

 

То что выше, работает и без разрешения прерываний.

С разрешёнными прерываниям работает стандартный кусок:

 

SDError = SD_WaitReadOperation();

while( SD_GetStatus() != SD_TRANSFER_OK );

 

Сектор читается корректно, но FatFs не работает!

При открытии файла - ошибка 4 - FR_NO_FILE, /* (4) Could not find the file */

 

Без DMA работает.

 

В чём подвох работы FatFs с DMA ? WORD_ACCESS стоит 0.

 

Всё разобрался с FatFs!

 

Проверил, что при чтении из файла библиотека суёт указатели, которые не выровнены на границу двойного слова(4 байта). Решил путём промежуточного буфера, выровненного на 16 байт для DMA:

 

/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

#define BLOCK_SIZE 512

unsigned char abuf[512] __attribute__((aligned (16))); //выровненный на 16 байт буфер

extern void align_error(void); //для отладки

DRESULT disk_read (
    BYTE pdrv,        /* Physical drive nmuber (0..) */
    BYTE *buff,        /* Data buffer to store read data */
    DWORD sector,    /* Sector address (LBA) */
    BYTE count        /* Number of sectors to read (1..128) */
)
{
    DRESULT dresult = RES_OK;
    SD_Error SDError;
    if( pdrv == SD_DISK_PDRV )
    {

if((((unsigned long int)buff)&0x00000003)!=0)align_error();    

for(int i=0;i<count;i++) //карта поддерживает только одно-блочную команду чтения, мультиблоки не работают :(
{
            SDError = SD_ReadBlock(abuf,(sector+i)*BLOCK_SIZE, BLOCK_SIZE); //читаем в выровненный буфер DMA
            
            #ifdef SD_DMA_MODE
            SDError = SD_WaitReadOperation();
            #endif
            
            while( SD_GetStatus() != SD_TRANSFER_OK );
            if(SDError != SD_OK)dresult = RES_ERROR;

                        memcpy(buff+(i<<9),abuf,512); //копируем в выходной буфер со смещением
}
        return dresult;
    }

    return RES_PARERR;
}

 

:rolleyes:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...указатели, которые не выровнены на границу двойного слова(4 байта)...

Двойное слово в Cortex-M4 это 8 байт. Не?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Двойное слово в Cortex-M4 это 8 байт. Не?

 

В традициях Старого Доброго ДОС-а считаю до сих пор словом - 2 байта (WORD)

4 байта - это уже двойное слово (DWORD) :biggrin:

 

Впрочем мне известно, что в кортексиках слово - 4 байта :rolleyes:

 

 

Пробовал отформатировать карту в винде на другой размер сектора - не даёт, только стандартный 512 байт.

Чем отформатировать можно карту с скеторами 2048 байт или больше?

Уменьшится ли время чтения?

 

В High speed mode есть смысл переводить чтоб быстрее читать с карты?

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот со времён "Старого Доброго ДОС-а" (; похоже, и не отличаете сектор (в SD 512 байт и никаких сусликов) от кластера (; (хоть 2кБ а хоть 32кБ)

Изменено пользователем Obam

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот со времён "Старого Доброго ДОС-а" (; похоже, и не отличаете сектор (в SD 512 байт и никаких сусликов) от кластера (; (хоть 2кБ а хоть 32кБ)

Старый добрый ДОС мне много счастья подарил :)

С сектором да, разобрался - 512 байт и не меняется.

Скачал SDFormatter, форматнул карточку им, произошло чудо - медленные карты теперь идут без заиканий.

 

Теперь вопрос: какой смысл использовать DMA для карт памяти через SDIO при использовании FatFs ?

 

Допустим надо считать порцию с файла. Вызывается чтение секторов, но ведь пока DMA не передаст все данные - прийдётся ждать! И сделать ничего не могу дальше, пока файл не считан. Оперативы - сколько в штатном STM32F407, так что спроецировать файловую систему в память не смогу (хотя в другом проекте такое успешно делал, но там памяти 64 МБ было).

 

Есть ли шанс реорганизовать работу Fatfs без ожидания завершения чтения секторов? Мне кажется, что нет.

Остаётся толко низкоуровневое чтение секторов одного за другим (причем блочное).

 

Пробовал переводить карту в High Speed Mode, тактовая частота 36 - 52 МГц ( менял делитель PLL_Q для USB, так как согласно эррате на STM32F407 Bypass там не работает) - выигрыша с медленными картами не дало.

 

Медленная карта - без обозначения класса скорости вообще на 2 ГБ.

С классом скорости 4 - работает отлично.

 

Я так понял, что разгон тактовой для карты памяти не имеет смысл, когда читаешь 1-секторный блок, так как задержки перед чтением у карты могут быть более длинными по времени.

 

Так ли это, как я тут изложил свои думалки?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...