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

но никакого эффекта... :(

Что делать - то?

Странно, проверка NOTBUSY у меня вполне себе работает.

 

Похоже, повторяется ситуация, как с командой ACMD41 - флаг NOTBUSY устанавливается мгновенно с CMDRDY...

ACMD41 - это особый случай, и там совсем другой "busy". Кстати, взвода CMDRDY перед проверкой NOTBUSY дожидаетесь?

 

ЗЫ: если ждать нужно ручками - зачем тогда вообще ввели специальный тип команды с ответом R1b? Толку то нет.

Потому что в противном случае контроллер возможно даже смотреть не будет busy status.

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


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

Кстати, взвода CMDRDY перед проверкой NOTBUSY дожидаетесь?

Конечно, такая же проверка:

    AT_MCI0->MCI_CMDR = comm_reg;
    do
    {
        status = AT_MCI0->MCI_SR;
    }
    while (!(status & AT_MCI_CMDRDY));

 

Попробовал и так: сначала CMD7(SELECT), а потом сразу CMD7(DESELECT).

Без разницы - получаю RTOE...

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


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

Ну, на CMD7(DESELECT) ответа и не должно быть.

 

Сдается мне, все правильно: повторная передача CMD7 переводит карту назад в stand-by, ответа и не должно быть.

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


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

Ну, на CMD7(DESELECT) ответа и не должно быть.

 

Сдается мне, все правильно: повторная передача CMD7 переводит карту назад в stand-by, ответа и не должно быть.

Да, спасибо, сейчас попробую отправить вслед за CMD7 другую команду.

Действительно, с CMD7 всё не так просто - судя по спецификации на эту команду карта отвечает только при переходе с STBY на TRAN.

 

ЗЫ: отправил следом ACMD51 - всё в порядке, ошибок нет :)

Впрочем, ошибок нет, даже если совсем убрать ожидание NOTBUSY. То ли это из-за низкой скорости интерфейса (работает пока на паре мегагерц, в отладочных соображениях), и карта успевает отпустить линию данных, то ли всё же контроллер отслеживает статус автоматически...

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


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

Ну вот, вроде сделал чтение сектора, теперь надо бы DMA подключать.

В даташите на этот счёт всё довольно мутно - какие-то дескрипторы, выравнивание по WORD и прочие грустные штуки :)

 

Мне бы организовать чтение\запись по произвольному адресу в памяти и с произвольным кол-вом секторов.

 

Может ли DMAC выполнять чтение\запись памяти по произвольному адресу, а не только по выровненному до слова?

Вроде бы есть поля в регистрах, этому сопутствующие.

 

С дескрипторами так и не пойму, допустим, надо мне прочесть с карты памяти 32 сектора последовательно в память, неужели для этого придётся создавать в памяти 32 дескриптора?

Можно ли обойтись одним так, чтобы чтение 32 секторов выполнялось за один раз, или придётся 32 раза перепрограммировать DMA (на каждый сектор)?

 

Судя по описанию в даташите, придётся возиться с каждым сектором :(

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


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

Впрочем, ошибок нет, даже если совсем убрать ожидание NOTBUSY. То ли это из-за низкой скорости интерфейса (работает пока на паре мегагерц, в отладочных соображениях), и карта успевает отпустить линию данных, то ли всё же контроллер отслеживает статус автоматически...

Ну, на CMD7 карте задумываться особо и не о чем.

 

Может ли DMAC выполнять чтение\запись памяти по произвольному адресу, а не только по выровненному до слова?

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

 

Можно ли обойтись одним так, чтобы чтение 32 секторов выполнялось за один раз, или придётся 32 раза перепрограммировать DMA (на каждый сектор)?

Теоретически можно обойтись одним. Контроллеру HSMCI в общем-то все равно, как запрограммирован контроллер DMA, лишь бы данные шли.

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


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

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

Понятно. Но зато не надо париться с выравниванием.

Что-то я слабо представляю, как вообще возможно всегда получать выровненный адрес в памяти, с которой будет работать файловая система в реальном приложении.

 

Хотя, среди примеров есть способ программирования DMA несколькими дескрипторами для передачи блока данных длиной не кратной 4.

Если только делать что-то похожее...

 

Среди регистров DMAC есть поля Source Chunk Transfer Size и Destination Chunk Transfer size.

Могут принимать значения 1 или 4.

Это что-то типа пакетной передачи?

 

Последнее, как я понимаю, будет лучше?

Теоретически можно обойтись одним. Контроллеру HSMCI в общем-то все равно, как запрограммирован контроллер DMA, лишь бы данные шли.

В общем, буду пробовать :)

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


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

Что-то я слабо представляю, как вообще возможно всегда получать выровненный адрес в памяти, с которой будет работать файловая система в реальном приложении.

А в чем проблема? Файловой системе все равно придется работать с целыми секторами, так почему бы их не выровнять по границе слова?

Кроме того, не стоит забывать, что ядру тоже не всегда удобно работать с не выровненными адресами - всякие memset/memcpy это замедлит.

 

Среди регистров DMAC есть поля Source Chunk Transfer Size и Destination Chunk Transfer size.

Могут принимать значения 1 или 4.

Это что-то типа пакетной передачи?

 

Последнее, как я понимаю, будет лучше?

Да, это значит, что HSMCI и DMA будут между собой обмениваться блоками по 4 слова, что, несомненно, лучше. Только не забудьте установить это поле и у HSMCI и у DMAC одинаково.

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


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

Теоретически можно обойтись одним. Контроллеру HSMCI в общем-то все равно, как запрограммирован контроллер DMA, лишь бы данные шли.

Но в чём проблема - в примерах для READ_SINGLE_BLOCK в качестве источника данных всегда указывается не регистр HSMCI_RDR, а так называемая "апертура" FIFOx Memory Aperture, при этом указатель на неё задаётся как инкрементируемый.

Это FIFO имеет граничный размер (HSMCI_FIFOx[x=0..255]), и при чтении\записи больших блоков не приведёт ли это к выходу за пределы этой памяти?

 

А в чем проблема? Файловой системе все равно придется работать с целыми секторами, так почему бы их не выровнять по границе слова?

Кроме того, не стоит забывать, что ядру тоже не всегда удобно работать с не выровненными адресами - всякие memset/memcpy это замедлит.

Ну, к примеру, если я захочу записать пару килобайт данных, пусть даже выровненных в памяти, в файл с произвольным смещением от его начала (не нулевым), то это будет как работать?

Сначала в буфер файловой системы считается первый сектор, в который частично попадают эти данные, в него копируется их кусок, затем этот сектор записывается.

Далее уже идёт прямая запись в сектора из памяти с абсолютно произвольного по выравниванию места, которое будет зависеть от начального смещения по файлу...

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


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

Но в чём проблема - в примерах для READ_SINGLE_BLOCK в качестве источника данных всегда указывается не регистр HSMCI_RDR, а так называемая "апертура" FIFOx Memory Aperture, при этом указатель на неё задаётся как инкрементируемый.

Упс. Да, забыл это обстоятельство. Тогда остается делать цепочку дескрипторов DMA. Впрочем, цепочку не обязательно - прерывания все равно будут, а перепрограммировать DMA - секундное дело.

 

Далее уже идёт прямая запись в сектора из памяти с абсолютно произвольного по выравниванию места, которое будет зависеть от начального смещения по файлу...

Идея понятна, да. У меня просто между файловой системой и картой проложен еще один уровень из дискового кэша и буфера записи, поэтому вопросов с выравниванием нет.

Тогда остается извернуться через поле OFFSET регистра HSMCI_DMA, но он, как я понимаю, действителен только для записи.

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


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

Упс. Да, забыл это обстоятельство. Тогда остается делать цепочку дескрипторов DMA. Впрочем, цепочку не обязательно - прерывания все равно будут, а перепрограммировать DMA - секундное дело.

Эх, вот если бы не было никакой "апертуры", а был бы регистр типа HCMI_RDR безо всякой инкрементации...

Почему так сделано, интересно?

 

Идея понятна, да. У меня просто между файловой системой и картой проложен еще один уровень из дискового кэша и буфера записи, поэтому вопросов с выравниванием нет.

Тогда остается извернуться через поле OFFSET регистра HSMCI_DMA, но он, как я понимаю, действителен только для записи.

Я так и понял, у Вас куча памяти, и идёт копирование данных сначала в выровненную память\кеш, а уже потом на карточку...

 

Да, непонятно с этим офсетом.

Думаю, тут можно поступить тоже используя дескрипторы - к примеру, понадобится три штуки для выравнивания сектора из 512 байт:

1. (MEMORY_ADDRESS & 0x03) - получаем 1 - 3 байта, для которых создаём дескриптор с BYTE доступом.

2. дескриптор с WORD доступом, обрабатывающий основную часть данных.

3. последний дескриптор BYTE, перебрасывающий последние 1-3 байта.

 

Чтобы уменьшить частоту прерываний, выделю память для 3-4 дескрипторов.

С другой стороны, возможно не стоит париться и сделать всё на BYTE дескрипторах, знать бы ещё, насколько загружена получается внутренняя шина...

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


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

Почему так сделано, интересно?

Надо полагать, для ускорения всего и вся :) Вполне возможно, что этому процессору оно и не нужно, но ведь IP-блоки тоже подвержены copy-paste.

 

Я так и понял, у Вас куча памяти, и идёт копирование данных сначала в выровненную память\кеш, а уже потом на карточку...

Именно так.

 

Думаю, тут можно поступить тоже используя дескрипторы - к примеру, понадобится три штуки для выравнивания сектора из 512 байт:

1. (MEMORY_ADDRESS & 0x03) - получаем 1 - 3 байта, для которых создаём дескриптор с BYTE доступом.

Так нельзя: контроллер HSMCI ждет на входе 32 бита и никак иначе. Не получится ему три байта скормить, кроме как через OFFSET, который и указывает, сколько байт нужно проигнорировать.

А вот с чтением, похоже, остается только байтовый доступ.

 

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


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

Так нельзя: контроллер HSMCI ждет на входе 32 бита и никак иначе. Не получится ему три байта скормить, кроме как через OFFSET, который и указывает, сколько байт нужно проигнорировать.

А вот с чтением, похоже, остается только байтовый доступ.

Да, с записью, оказывается, все много проще, задать offset и дело в шляпе :)

Странно, что для чтения не предусмотрели такую фичу вместо сомнительного ROPT...

 

Интересно, а как себя поведет DMA при возникновении ошибки, к примеру, при чтении, если карта не отдаст количество данных, на которые он запрограммирован?

Повиснет?

 

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


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

Интересно, а как себя поведет DMA при возникновении ошибки, к примеру, при чтении, если карта не отдаст количество данных, на которые он запрограммирован?

Повиснет?

Карта не отдать просто не сможет: хост подает клок и снимает данные вне зависимости от того, что думает карта. Другое дело, что в таком случае появится ошибка CRC, но DMA об этом и не узнает.

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


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

Карта не отдать просто не сможет: хост подает клок и снимает данные вне зависимости от того, что думает карта. Другое дело, что в таком случае появится ошибка CRC, но DMA об этом и не узнает.

Ну как же - есть же Start Bit, есть специальные токены начала данных (по крайней мере в режиме SPI были), то есть хост может определить момент появления данных.

К примеру, если после команд чтения данных не ждать установки флага NOTBUSY и сразу попытаться подавать следующую команду - получаем зависон на циклическом опросе флага AT_MCI_RXRDY, который никогда уже не установится - карточка-то молчит.

Или просто попробовать прочитать больше данных, чем карта отдаёт - скажем, вместо 8 байт команды ACMD51 попытаться прочесть 9 - аналогичный зависон...

 

То есть хост определяет, отдаёт карта данные, или нет с точностью до байта.

Но это касается работы без DMA, с ним, возможно, будет несколько иначе...

 

PS: хотя бог знает, может просто я чего нибудь напутал... :)

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


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

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

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

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

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

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

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

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

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

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