‮Сдвиг по фазе (kincajou) wrote,
‮Сдвиг по фазе
kincajou

Category:

worklog: SPI2 DMA

В микроконтроллере STM32F103 несколько независимых модулей SPI. В теории, они друг от друга ничем не отличаются. На практике, первый из модулей висит на "быстрой" (72 МГц) периферийной шине, а все остальные - на "медленной" (36МГц). Каналы DMA тоже должны быть одинаковыми, но вот незадача: SPI1 прекрасно работает через DMA (что подтверждается более чем успешной реализацией USB Mass Storage, читающей данные с флешки именно так), а вот SPI2 через DMA, похоже, может только передавать данные, но при попытке чтения в целевой памяти будут только нули!

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

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

С другой стороны, как-то обидно. И в errata ничего нет - но если это у меня ляп, то я его не вижу в упор. Функция точно такая же, как для SPI1, только регистры и каналы другие (да, проверял, разными способами - железяка проинициализирована правильно, каналы DMA используются какие надо каналы, всё ДОЛЖНО работать).

Upd выяснил чть больше подробностей, всё ещё печальнее: передача данных тоже глючит. В общем, если надо просто передавать поток данных, то делаю это так:
1) настраиваю канал "из памяти в устройство", автоинкремент памяти включен (надо передать массив), адрес источника данных - начало приёма, автоинкремент периферийного адреса выключен и адрес приёмника - регистр SPI2->DR; количество данных - длина массива
2) настраиваю канал "из устройства в память" (если SPI не читать после передачи данных, формируется ошибка overrun), автоинкремент памяти ВЫКЛЮЧЕН, в качестве приёмника данных - переменная-пустышка, источник данных всё тот же регистр, длина та же.
3) включаю сам модуль SPI. Это вызывает автоматическое срабатывание всех узлов.
4) дожидаюсь взведения флагов "транзакция завершена", выключаю SPI

So far so good, передаётся именно то, что мне было нужно. На втором этапе, если мне надо принять данные (протокол связи аналогичен тому, что используется в SPI Serial Flash - сначала высылаем команду, затем либо читаем, либо высылаем данные), меняются настройки автоинкремента и адреса источников-приёмников данных:

5) "из памяти в устройство" автоинкремент выключен, пересылается одини и тот же байт-пустышка (ибо сейчас нужен только сигнал SCK, а генерируется он только тогда, когда мастер-устройство шлёт данные!).
6) "из устройства в память" автоинкремент включен, адрес приёмника данных - массив, который нам надо заполнить.
7) дожидаюсь взведения флагов "транзакция завершена", выключаю SPI

В случае с модулем SPI1, на котором висит флешка, алгоритм работает прекрасно: читает, пишет, всё очень быстро и безошибочно. В случае же с модулем SPI2 первая половина, с записью данных, работает, а вторая - заковыристым образом фейлит: количество байтов верное, но вместо передачи байта-пустышки передаётся либо вообще непонятно что, либо ПОСЛЕДНИЙ ПРИНЯТЫЙ БАЙТ.. такое ощущение, что DMA вместо того, чтобы читать байт-пустышку (адрес коего занесён в регистр CMAR) и записывать его содержимое в целевой регистр, берёт данные из целевого регистра и сразу кладёт их обратно туда же.

Бред какой-то. В интернете упоминаний об аналогичной проблеме не нашёл, errata молчит.

Переписал на half-duplex работу (т.е. если надо только передавать, то игнорируется приёмник, а если надо только принимать, то отключается передатчик) -- пофиг, то же бредовый результат, хоть и слегка иной.
Tags: радио
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments