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

STM32H7 SDMMC

Добрый день.

Пытаюсь подключить SD карту. Раньше делал уже это на F4, теперь переделываю под новый SDMMC в h7.

Контроллер STM32H743, карта подключена по SDIO 4-bit, не получаю ответ на команды инициализации. 

Карта подключена "классическим" способом, D0-D4, CMD, CLK. В схемах на EVAL платы подключение другое, для поддержки карт с питанием 1.8в (и большей частотой).

Использую SDMMC1. Тактирование от PLL1, на выходе DIVQ1 48Mhz. На время инициализации ставлю делитель 60. 48Mhz/(60*2) = 400kHz 

Включение SDMMC1:

	RCC->AHB3ENR |= RCC_AHB3ENR_SDMMC1EN;

	RCC->AHB3RSTR |= RCC_AHB3RSTR_SDMMC1RST;
	for(uint8_t i=0; i<0x10; i++) asm volatile("nop");
	RCC->AHB3RSTR &= ~RCC_AHB3RSTR_SDMMC1RST;

	SDIO->CLKCR = SDIO_CLK_DIV_INIT; //#define SDIO_CLK_DIV_INIT   ((uint32_t)0x03C)
	SDIO->POWER |= SDMMC_POWER_PWRCTRL;
	
	//Ожидание, 74 цикла
	for(uint32_t i=0; i<0x1000; i++) asm volatile("nop");

После включения питания, в реф. мане  указано подождать 74 цикла. Циклы видимо по линии SD_CLK, поэтому тут пока задержка просто "на глаз" (оптимизация на данный момент выключена). В любом случае, я в отладчике шагаю, так что оно точно успевает 74 "тикнуть".

После этого, если я правильно читаю, карта готова к инициализации. Для отправки команд использую такую конструкцию:

uint8_t SD_Cmd(uint8_t cmd, uint32_t arg, uint16_t response_type, uint32_t *response){

	SDIO->ICR = SDMMC_ICR_CCRCFAILC | SDMMC_ICR_CTIMEOUTC | SDMMC_ICR_CMDRENDC | SDMMC_ICR_CMDSENTC;
	SDIO->ARG = arg;
	SDIO->CMD = (uint32_t)(response_type | cmd | SDMMC_CMD_CPSMEN);

	while((SDIO->STA & (SDMMC_STA_CMDSENT|SDMMC_STA_CMDREND)) == 0){asm("nop");};

	if (response_type != SDIO_RESP_NONE) {
		response[0] =	SDIO->RESP1;
		response[1] =	SDIO->RESP2;
		response[2] =	SDIO->RESP3;
		response[3] =	SDIO->RESP4;
	}
	
	if (SDIO->STA & SDMMC_STA_CTIMEOUT) return 2;
	if (SDIO->STA & SDMMC_STA_CCRCFAIL) return 3;  
	return 0;
}

И пробую инициализировать карту: 

Отправляю команду CMD_0 без ожидания ответа. Команда проходит, в STA поднимается флаг CMDSENT, ошибок нет.

Отправляю команду CMD_8. Аргумент - CHECK PATTERN 0x01A, ответ R7(короткий). В STA поднимается флаг CMDREND (флагов ошибок нет) , но в RESP регистрах нули, а должен был придти CHECK PATTERN. 

Переменная response на которую передаю указатель расположена в RAM_D1. Но я в отладчике на содержимое регистров смотрю, что ответа нет.

На время отладки MPU отключен, кеш отключен.

На второй такой же плате установлен F429 (корпус LQFP176, они pin-to-pin заменяемы), там этаже SD карта  работает без проблем. Т.е. с разводкой все должно быть нормально.

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


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

Вопрос снимается :)

Стал проверять "невозможное", оказалось в ините GPIO для ноги CMD не очищал предварительно регистр MODER, соответственно при операции "OR" он оставался в значении по умолчанию 11-Аналог, а не альт. функция.

Но поскольку создал тему, поинтересуюсь про новые возможности SDMMC. Обычные SD карты памяти, те что можно в магазине купить, поддерживают режимы работы с увеличенной частотой и питанием 1.8в? Насколько больше скорость чтения и записи?

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


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

2 minutes ago, sst78rus said:

Обычные SD карты памяти, те что можно в магазине купить, поддерживают режимы работы с увеличенной частотой и питанием 1.8в? Насколько больше скорость чтения и записи?

В магазине можно купить UHS-I. Чтение до 100МБайт/с, запись - как повезет.

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


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

Удалось запустить чтение, содержимое каталога через FATFs прочитал.

А как правильно работать с IDMA? Максимальный размер буфера который можно указать - 0xFF * 32 = 8160 байт. А если нужно больше? "В ручную" разбивать буфер на куски? Или можно как-то связать с MDMA, и отправлять сразу буфер большего размера? 

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


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

On 10/24/2019 at 5:08 PM, sst78rus said:

Максимальный размер буфера который можно указать - 0xFF * 32 = 8160 байт.

Речь про регистр IDMABSIZE я так понимаю? Вы описание его внимательно прочитайте - этот регистр используется только в режиме с двумя буферами. В обычном режиме через IDMA можно пропустить столько сколько нужно данных (размер задается через DLEN).

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


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

Тоже сейчас ковыряюсь с h743 и sd, запускаю без конвертора напряжений на 3.3v

Через hal пока нормально работает только поллинг. Как только включаю irq/idma, чтение тупит и по тайм-ауту вываливается. irq какие-то прилетают, отдаю в hal. но в дебаггере ловлю флаг overrun (вероятно из-за остановки дебагером). Но поллинг не устраивает, ибо нужна скорость. Задач много, своё писать и hal глубоко расковыривать не очень хочется.

Если есть рабочая реализация под rtos (желательно без hal) может поделитесь наработками? Бюджет обговариается :)

 

upd: вроде разобрался. оказывается DMA пишет только в регион памяти AXISRAM.

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


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

14 часов назад, jeka сказал:

Тоже сейчас ковыряюсь с h743 и sd, запускаю без конвертора напряжений на 3.3v

Через hal пока нормально работает только поллинг. Как только включаю irq/idma, чтение тупит и по тайм-ауту вываливается. irq какие-то прилетают, отдаю в hal. но в дебаггере ловлю флаг overrun (вероятно из-за остановки дебагером). Но поллинг не устраивает, ибо нужна скорость. Задач много, своё писать и hal глубоко расковыривать не очень хочется.

Если есть рабочая реализация под rtos (желательно без hal) может поделитесь наработками? Бюджет обговариается :)

upd: вроде разобрался. оказывается DMA пишет только в регион памяти AXISRAM.

Вот пример работы https://github.com/Sergey1560/h7_sdmmc

Это не готовая библиотека, а просто пример, чтобы проверить работает ли вообще :) В данном примере выключен режим работы карты HighSpeed. Код переключения в этот режим скопипастил (источники в sdio.h есть), на F4 работало вроде бы быстрее. Под h7 его надо переписать.

В sdio.c объявлен здоровый массив buf_copy. Я код взял из готового проекта и там иногда от FATFs приходил запрос на запись не выровненного буфера, от чего DMA падал в hardfault. Я просто копировал в выровненный буфер и уже его читал/писал в карту. Сейчас правда у меня есть подозрения, что FATFs передавал не выровненный блок потому, что я его не выровненным передавал FATFs :) Вообщем обратите на это внимание. Я добавил вывод сообщений, если в функцию чтения/записи на SD передается не выровненный блок, в тестовой записи-чтении срабатываний не было. 

Тот пример, что в коде, пишется со скоростью около 1.2Мб/с, читается около 8.

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


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

а всего-то надо в FatFS обеспечить выравнивание внутренних данных в структуре и самой её.

Я в своем проекте обеспечил так:
 


typedef FATFSALIGN_BEGIN struct {
	BYTE	fs_type;		/* Filesystem type (0:N/A) */
	BYTE	pdrv;			/* Physical drive number */
	BYTE	n_fats;			/* Number of FATs (1 or 2) */
	BYTE	wflag;			/* win[] flag (b0:dirty) */
	BYTE	fsi_flag;		/* FSINFO flags (b7:disabled, b0:dirty) */
	WORD	id;				/* Volume mount ID */
	WORD	n_rootdir;		/* Number of root directory entries (FAT12/16) */
	WORD	csize;			/* Cluster size [sectors] */
#if FF_MAX_SS != FF_MIN_SS
	WORD	ssize;			/* Sector size (512, 1024, 2048 or 4096) */
#endif
#if FF_USE_LFN
	WCHAR*	lfnbuf;			/* LFN working buffer */
#endif
#if FF_FS_EXFAT
	BYTE*	dirbuf;			/* Directory entry block scratchpad buffer for exFAT */
#endif
#if FF_FS_REENTRANT
	FF_SYNC_t	sobj;		/* Identifier of sync object */
#endif
#if !FF_FS_READONLY
	DWORD	last_clst;		/* Last allocated cluster */
	DWORD	free_clst;		/* Number of free clusters */
#endif
#if FF_FS_RPATH
	DWORD	cdir;			/* Current directory start cluster (0:root) */
#if FF_FS_EXFAT
	DWORD	cdc_scl;		/* Containing directory start cluster (invalid when cdir is 0) */
	DWORD	cdc_size;		/* b31-b8:Size of containing directory, b7-b0: Chain status */
	DWORD	cdc_ofs;		/* Offset in the containing directory (invalid when cdir is 0) */
#endif
#endif
	DWORD	n_fatent;		/* Number of FAT entries (number of clusters + 2) */
	DWORD	fsize;			/* Size of an FAT [sectors] */
	DWORD	volbase;		/* Volume base sector */
	DWORD	fatbase;		/* FAT base sector */
	DWORD	dirbase;		/* Root directory base sector/cluster */
	DWORD	database;		/* Data base sector */
	DWORD	winsect;		/* Current sector appearing in the win[] */
	FATFSALIGN_BEGIN  BYTE	win[FF_MAX_SS] FATFSALIGN_END;	/* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFSALIGN_END FATFS;



/* File object structure (FIL) */

typedef FATFSALIGN_BEGIN struct {
	FFOBJID	obj;			/* Object identifier (must be the 1st member to detect invalid object pointer) */
	BYTE	flag;			/* File status flags */
	BYTE	err;			/* Abort flag (error code) */
	FSIZE_t	fptr;			/* File read/write pointer (Zeroed on file open) */
	DWORD	clust;			/* Current cluster of fpter (invalid when fptr is 0) */
	DWORD	sect;			/* Sector number appearing in buf[] (0:invalid) */
#if !FF_FS_READONLY
	DWORD	dir_sect;		/* Sector number containing the directory entry (not used at exFAT) */
	BYTE*	dir_ptr;		/* Pointer to the directory entry in the win[] (not used at exFAT) */
#endif
#if FF_USE_FASTSEEK
	DWORD*	cltbl;			/* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
#if !FF_FS_TINY
	FATFSALIGN_BEGIN BYTE	buf[FF_MAX_SS] FATFSALIGN_END;	/* File private data read/write window */
#endif
} FATFSALIGN_END FIL;

 

У меня с GCC так:

#define FATFSALIGN_BEGIN __attribute__ ((aligned (32)))
#define FATFSALIGN_END /* nothing */

 

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


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

Мне кажется смысла мало заморачиваться с выравниванием. Проще dma переключить на байтовый режим и всё. ибо 25мб/s не та скорость чтоб память ощутимо тормозить начала.

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


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

8 hours ago, jeka said:

Проще dma

IDMA? У нас тут H7 фигурирует. Интересно, как Вы это сделаете. А с выравниванием еще из соображений DataCache лучше.

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


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

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

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

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

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

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

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

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

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

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