Jump to content

    
korotaev

STM32H743 mass storage

Recommended Posts

4 минуты назад, mantech сказал:

но потеряем в безопасности при откл. питания в частности.

Вроде речь шла только о кешировании чтения....  :unknw:

Не надо мешать мух с котлетами - при записи совсем другой алгоритм.

Share this post


Link to post
Share on other sites
Только что, jcxz сказал:

Вроде речь шла только о кешировании чтения....

При чтении безопасно, кроме усложнения кода ничем не грозит...

Share this post


Link to post
Share on other sites
On 2/25/2021 at 11:21 AM, korotaev said:

STM32H743. Чтение SD карты в режиме Polling.

Два прибора. Один на базе STM32F437, другой- STM32H743. Для каждого прибора скорость обмена данными по USB каналу не менее 28 Мбайт/сек. В каждом стоят одинаковые SD карты UHS-I без трансивера.

ПО для STM32F437 с использованием SPL, STM32H743 – CubeMX v.6.1, пакет для микроконтроллера STM32Cube FW_H7 V1.8.0.

Имею для прибора на STM32H743 очень маленькую скорость чтения данных в режиме USB флэшки. Проверял так.

C приборов в режиме mass storage (Polling) читается один и тот же файл размерностью 256 Мбайт. Клок для карточек в приборах одинаковый. Средняя скорость чтения для STM32F437 примерно 7 Мбайт в секунду, для STM32H743 – всего 1.5 Мбайт в секунду.

Для многих это не новость. Есть подобные сообщения на эту тему.

Вопрос: можно ли увеличить скорость чтения для H743, если перевести обмен данными в режим DMA (iDMA)?

 

     

             STM32H743, mass storage USB device, Windows.

             В режиме Polling работает, но скорости маленькие (запись 300 – 600 кБайт/сек, чтение в среднем 1.5 МБайт/сек). Проблем с USB железом нет. Скорость  передачи данных до 28 МБайт/сек.

             В режиме DMA не работает. Код внизу. Проводник открывает Окно диска и дополнительно выскакивает окно с предложением "Форматировать диск".

             

              В файле “usbd_storage_if.c”

               int8_t STORAGE_Read_HS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)

               {

               int8_t ret = USBD_FAIL;

               RxStatus0 = 0;  //глобальная переменная

                 if (BSP_SD_ReadBlocks_DMA(0, (uint32_t*)buf, (uint32_t)blk_addr, blk_len) == HAL_OK)

                 {

                                //while (RxStatus0 == 0) {};  //Ожидаю Callback

                               if (Wait_SDCARD_1_Ready() == HAL_OK)

                               ret = USBD_OK;

                 }

                return ret;

               }

 

            void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)

            {

            if (hsd->Instance  == SDMMC1)

                {

                  RxStatus0 = 1;

               }

            }

 

 Очень странный момент:

- Если раскомментировать while (RxStatus0 == 0) {};  //Ожидаю Callback ,

то программа виснет на этой строке, т.е. прерывания SDMMC1 и вызов HAL_SD_RxCpltCallback не происходят.

- Если закомментировать эту строку, то прерывания SDMMC1 и вызов HAL_SD_RxCpltCallback не происходят также.

- Однако, если поставить точку останова на где-нибудь после этой строки, программа остановиться на этой точке и потом продолжить программу, то прерывания и вызов callback происходят. Прерывание и callback вызываются только после выхода из функции STORAGE_Read_HS.

 

Видел примеры, где внутри STORAGE_Read_HS опрашивается состояние  RxStatus0, которое изменяется в callback. И нет никакого зависания.

Более того, у меня DMA версия работала, но  также с маленькими скоростями. Теперь не могу вернуться хотя бы к работающему примеру с DMA.

Подскажите, кто знает в чём засада.

 

Edited by korotaev

Share this post


Link to post
Share on other sites
02.04.2021 в 11:14, korotaev сказал:

RxStatus0, которое изменяется в callback. И нет никакого зависания.

Никто ж не знает, что это за коллбэк и чего он делает, а самое главное - как? В ту сторону и "копайте"...

Share this post


Link to post
Share on other sites

Есть стандартная проблема при обработке прерываний - перед выходом из прерывания нужно проверить, не пришло ли еще одно и, если пришло обработать его и т.д. Если этого не сделать - то можно пропустить следующее прерывание, т.к. оно может быть сброшено при выходе из прерываний. По хорошему - в начале обработки сбросить pending бит, а в конце проверить не встал ли он снова.

 

Если точнее, в начале сбросить источник запроса на прерывание, сбросить pending бит, в конце - проверить pending бит.

Share this post


Link to post
Share on other sites
3 часа назад, rudy_b сказал:

Есть стандартная проблема при обработке прерываний - перед выходом из прерывания нужно проверить, не пришло ли еще одно и, если пришло обработать его и т.д. Если этого не сделать - то можно пропустить следующее прерывание, т.к. оно может быть сброшено при выходе из прерываний. По хорошему - в начале обработки сбросить pending бит, а в конце проверить не встал ли он снова.

Чушь! Это невозможно в принципе (в конце проверить не встал ли он снова). Посмотрите как устроен любой ISR чтобы понять "почему".

Стандартный способ обработки прерываний от любых источников на Cortex-M:

1. Сбросить флаг прерывания (в начале ISR).

2. Обработать прерывание.

3. Выйти из ISR.

Ничего "в конце ISR" проверять не надо, ибо - бесполезно. Если новое прерывание возникнет во время работы ISR, то сразу после выхода из ISR будет вход по новой в него.

Вот и всё. "Проблема" надуманная.

Share this post


Link to post
Share on other sites
4 часа назад, rudy_b сказал:

По хорошему - в начале обработки сбросить pending бит, а в конце проверить не встал ли он снова.

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

Edited by mantech

Share this post


Link to post
Share on other sites
2 часа назад, mantech сказал:

если у вас запрос на прерывание выставляется в процессе обработки предыдущего, а еще если и не один раз за это время, значит либо неправильно проработан алгоритм работы с прерываниями

На одном векторе часто висят обработчики обработчики разных событий (прием, готовность передатчика, ошибки и т.п.), и одни из них могут возникать во время обработки других. Это совершенно штатная ситуация даже при самом правильном обрабочике. Один вектор на каждый флаг всегда был непозволительной роскошью. Достаточно просто в начале обработчика считать флаги во временную переменную и сбросить только те флаги, которые в этой переменной установлены. И именно эти флаги и обрабатывать.

Share this post


Link to post
Share on other sites
18 минут назад, Сергей Борщ сказал:

На одном векторе часто висят обработчики обработчики разных событий (прием, готовность передатчика, ошибки и т.п.), и одни из них могут возникать во время обработки других.

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

Share this post


Link to post
Share on other sites
21 hours ago, jcxz said:

Чушь! Это невозможно в принципе (в конце проверить не встал ли он снова). Посмотрите как устроен любой ISR чтобы понять "почему".

Стандартный способ обработки прерываний от любых источников на Cortex-M:

1. Сбросить флаг прерывания (в начале ISR).

2. Обработать прерывание.

3. Выйти из ISR.

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

В начале нужно сбросить не флаг прерывания, а источник запроса, и, только потом, сбрасывать флаг (pending бит)

Share this post


Link to post
Share on other sites
2 часа назад, rudy_b сказал:

В начале нужно сбросить не флаг прерывания, а источник запроса, и, только потом, сбрасывать флаг (pending бит)

А что такое "источник запроса"? И каким образом его нужно сбросить?

Share this post


Link to post
Share on other sites

В стандартных случаях источником запроса на прерывание является периферия, DMA и т.п. Например при приеме байта UART при разрешенном прерывании, таймер, SPI и т.д. Они устанавливают запрос на прерывание, он отрабатывается процессором и запускается соответствующий обработчик прерывания. Для сброса источника прерывания, как правило, нужно считать соответствующий регистр или ручками сбросить бит в периферии. А, затем, снять бит в NVIC процессора. Последнее может делаться автоматически при возврате из прерывания по reti.

Share this post


Link to post
Share on other sites

А вот мне кажется, что именно Вы, @rudy_b, не совсем понимаете, о чем говорите.

Последним сообщением Вы просто, по сути, пересказали то, о чем говорил @jcxz. Ведь тезисом

22 часа назад, rudy_b сказал:

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

явно затевался, видимо, какой-то аргументированный спор.

И не надо снимать бит в NVIC - в некоторых случаях так можно только потерять событие.
Да и нет в Cortex-Mx никакого RETI. Для них ISR не отличается по ABI от обычной функции.

Share this post


Link to post
Share on other sites
7 часов назад, rudy_b сказал:

А, затем, снять бит в NVIC процессора. Последнее может делаться автоматически при возврате из прерывания по reti.

Давайте вы почитаете учебник по теме "Ядро Cortex-M. Механизм прерываний.", узнаете что такое NVIC, как работают прерывания в нём, какие там есть флаги, зачем они и как производится вход и возврат из прерывания в Cortex-M. Как используется регистр LR при этом. Почему бесполезно в конце ISR проверять наличие флага нового прерывания. Почему в типичном ISR не нужно трогать pending-биты и другие биты в NVIC.

А потом придёте на пересдачу. А пока вам - назачёт по теме.

Arlleex вам уже задал начало правильного направления и подсказал некоторые моменты.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.