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

PDC и SPI в AT91SAM7X

Всем привет!

 

Решил для разгрузки процессора AT91SAM7X128 перенести весь обмен данными (UART, SPI) на работу через PDC. Написал один код для работы с PDC (pdc.h и pdc.cpp). А код для работы с UART и SPI его, соответственно, использует. Так вот UART теперь работает просто замечательно, а вот SPI - нет. Настроен он у меня для работы с Variable Peripheral, т.е. номер chip select'а указывается прямо в регистре данных (да, учёл, что PDC в этом режиме SPI переписывает куски по 4 байта за раз - значения регистра отправки).

 

Проблема вот в чём: если SPI работает через прерывания (AT91C_SPI_RDRF и AT91C_SPI_TXEMPTY), то все отправляются как надо, а если включить PDC и использовать прерывания AT91C_SPI_ENDRX и AT91C_SPI_ENDTX (при абсолютно тех же настройках самого контроллера SPI), то всё работает так же, и переписываются те же данные, но chip select не стробирует, а один раз устанавливается на низкий уровень в самом начале передачи буфера, а потом, в самом конце, опять возвращается на высокий уровень. Бит AT91C_SPI_LASTXFER, помещенный в каждую ячейку буфера для отправки, не помогает.

 

Нашёл на просторах инета вот такой вот ответ:

Using PDC, how to toggle SPI Chip Select between each data transfer?

Здесь рекомендуют в буфере каждую вторую ячейку использовать как заглушку, отправляя данные на неподключённый chip select. Тогда chip select начнёт стробироваться. Но ведь нужно тогда в 2 раза бОльший массив иметь, да и вообще, какие-то костыли получаются.

 

Как правильно сделать, чтобы SPI нормально через PDC работал в режиме Variable Peripheral?

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


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

Всем (кто юзает AT91) давно известно, что чипселект глючный у этих камней. Основная масса решает проблемы обычным "ногодрыганием" выделенной под CS линии.

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


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

Проблема вот в чём: если SPI работает через прерывания (AT91C_SPI_RDRF и AT91C_SPI_TXEMPTY), то все отправляются как надо, а если включить PDC и использовать прерывания AT91C_SPI_ENDRX и AT91C_SPI_ENDTX (при абсолютно тех же настройках самого контроллера SPI), то всё работает так же, и переписываются те же данные, но chip select не стробирует, а один раз устанавливается на низкий уровень в самом начале передачи буфера, а потом, в самом конце, опять возвращается на высокий уровень. Бит AT91C_SPI_LASTXFER, помещенный в каждую ячейку буфера для отправки, не помогает.

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

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


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

prottoss

Ну это всё понятно, конечно, но дёргание chip select'а через PIO делает бесполезным использование DMA.

 

DmitryM

Почему нормально? Такое происходит только если в регистре настройки конкретного chip select'а выставлен в 1 бит CSAAT (Chip Select Active After Transfer), только тогда при передаче байт один за другим chip select будет выставлен на низкий уровень, а на высокий вернётся только после передачи элемента данных, где выставлен в 1 бит LASTXFER (Last Transfer). Так всё и работает при реализации передачи через прерывания. При работе через PDC так почему-то не работает, бит LASTXFER ни на что не влияет.

 

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

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


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

Ну это всё понятно, конечно, но дёргание chip select'а через PIO делает бесполезным использование DMA.
О как. Это как так???

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


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

prottoss

Мне нужно отправлять по SPI данные сразу на несколько устройств. В одном случае я делаю один буфер и всё. А в случае управления chip select'ом через PIO я должен буфер разбить на несколько: по одному для каждого устройства, и отправлять их по очереди, чтобы chip select менять между отправками. Это лучше, конечно, чем отправлять через прерывания, но всё равно 1) неудобно и 2) не так эффективно.

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


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

DmitryM

Почему нормально? Такое происходит только если в регистре настройки конкретного chip select'а выставлен в 1 бит CSAAT (Chip Select Active After Transfer), только тогда при передаче байт один за другим chip select будет выставлен на низкий уровень, а на высокий вернётся только после передачи элемента данных, где выставлен в 1 бит LASTXFER (Last Transfer). Так всё и работает при реализации передачи через прерывания. При работе через PDC так почему-то не работает, бит LASTXFER ни на что не влияет.

Это Вы неправильно понимаете CSAAT. Просто при работе без ДМА Вы не успеваете записать в TDR и чип селект снимается. Уменьшите частоту SPI и без PDC также чип-селект не будет дергаться на каждый байт(слово). Смотрите подробнее Figure 28-8 Peripheral Deselection

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


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

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

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

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

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

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

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

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

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

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