Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Сброс DMA1 и последующая настройка в STM32
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
ArtDenis
Приветствую. Опытным путём было установлено, что если сбросить DMA1 таким кодом
Код
RCC->AHBRSTR |= RCC_AHBRSTR_DMA1RST;
RCC->AHBRSTR &= ~RCC_AHBRSTR_DMA1RST;

и сразу после этого немедленно начать настраивать канал DMA, то DMA не будет работать. Если же после сброса поставить небольшую задержку (сейчас у меня стоит 10 микросекунд), то всё работает. Кто-нибудь сталкивался с таким поведением? Как правильно проверять, что канал DMA уже можно настраивать после сброса DMA?

PS: камень STM32L151CBT6
adnega
Цитата(ArtDenis @ Sep 14 2014, 14:37) *
Приветствую. Опытным путём было установлено, что если сбросить DMA1 таким кодом
Код
RCC->AHBRSTR |= RCC_AHBRSTR_DMA1RST;
RCC->AHBRSTR &= ~RCC_AHBRSTR_DMA1RST;

и сразу после этого немедленно начать настраивать канал DMA, то DMA не будет работать. Если же после сброса поставить небольшую задержку (сейчас у меня стоит 10 микросекунд), то всё работает. Кто-нибудь сталкивался с таким поведением? Как правильно проверять, что канал DMA уже можно настраивать после сброса DMA?

PS: камень STM32L151CBT6

Задержка нужна не только после сброса, но и после подачи тактового сигнала на периферийный блок.
Лучше использовать не цикл, а барьер.
ArtDenis
Цитата(adnega @ Sep 14 2014, 16:49) *
Лучше использовать не цикл, а барьер.

А можно поподробнее про барьер?
adnega
Цитата(ArtDenis @ Sep 14 2014, 15:10) *
А можно поподробнее про барьер?

__DSB()

/** \brief Data Synchronization Barrier

This function acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
ArtDenis
Работает, однако! Спасибо cool.gif
Добавил __DSB() в свою либу

Хм. Почему-то этого __DSB в SPL не наблюдается... И задержек тоже там нету.
Если откомпилировать проект, использующий SPL, с крутыми настройками оптимизации (O3 + LTO), то возможно он перестанет работать.
adnega
Цитата(ArtDenis @ Sep 14 2014, 17:13) *
Работает, однако! Спасибо cool.gif
Добавил __DSB() в свою либу

Хм. Почему-то этого __DSB в SPL не наблюдается... И задержек тоже там нету.
Если откомпилировать проект, использующий SPL, с крутыми настройками оптимизации (O3 + LTO), то возможно он перестанет работать.

Барьеры скорее всего нужны для многопроцессорных систем.
Вы просто __NOP() не пробовали?
Эти функции определены в core_cmInstr.h
ArtDenis
Цитата(adnega @ Sep 14 2014, 19:16) *
Барьеры скорее всего нужны для многопроцессорных систем.
Вы просто __NOP() не пробовали?

Так после сброса устройства нужен __DSB() или нет? Может как-то флаг где-нибудь надо смотреть?
__NOP() не пробовал.
adnega
Цитата(ArtDenis @ Sep 14 2014, 17:19) *
Так после сброса устройства нужен __DSB() или нет? Может как-то флаг где-нибудь надо смотреть?
__NOP() не пробовал.

Нужно дать устройству инициализироваться. Можно поискать в документации сколько циклов на это требуется.
Я пользуюсь другим подходом: стараюсь между включением тактового сигнала и непосредственной работой с регистрами вставлять какой-то полезный код.
ArtDenis
Т.е. совет ставить __DSB() неверный?
adnega
Цитата(ArtDenis @ Sep 14 2014, 18:02) *
Т.е. совет ставить __DSB() неверный?

Кто знает...
Я бы советовал:
1. Не пользоваться сбросом, а пользоваться нормальной инициализацией каналов со сбросом флагов и т.п.
2. Не использовать микросекундные задержки где попало.
3. Найти ответы на вопросы в документации.
jcxz
Как я понимаю - наличие NOP не гарантирует, что последующая запись в периферийное адресное пространство не выполниться ранее чем та запись, которая перед NOP.
Это касается тех случаев, когда периферия сидит на разных периферийных шинах да ещё с разным частотами тактирования.
Могу предположить, что RCC сидит на одной APB, а DMA - на другой (хотя в даташит мне заглядывать лень sm.gif.
Так что DSB - нужно, имхо.
adnega
Цитата(jcxz @ Sep 14 2014, 18:21) *
Могу предположить, что RCC сидит на одной APB, а DMA - на другой

Тоже была такая версия. Причем на STM32L могут в целях энергосбережения быть выставлены такие делители, что потребуется больше одного NOP для корректной работы.
ArtDenis
Тут мне сообщили что вариант с __DSB() правильный. Остановлюсь на нём.
jcxz
Цитата(ArtDenis @ Sep 15 2014, 10:04) *
Тут мне сообщили что вариант с __DSB() правильный. Остановлюсь на нём.

Правильно сообщили sm.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.