Моя периферийная периферия AT91SAM7X512 отключается по времени X (меняется X), который я пишу на SPI_TDR
. В результате процессор зависает во время цикла, который проверяет флаг TDRE
в SPI_SR
. Этот цикл while находится в функции SPI_Write()
, которая относится к программному обеспечению/библиотеке, предоставляемой ATMEL. Проблема возникает произвольно - иногда все работает нормально, и иногда она терпит неудачу при повторных попытках (attemp = загрузка одного и того же двоичного файла в MCU и запуск программы).SPI периферийное устройство AT91SAM7X512 отключается при записи в SPI_TDR
Конфигурации (определяется в порядке написания):
SPI_MR
:MSTR
= 1PS
= 0PCSDEC
= 0PCS
= 0111DLYBCS
= 0
SPI_CSR[3]
:CPOL
= 0NCPHA
= 1CSAAT
= 0BITS
= 0000SCBR
= 20DLYBS
= 0DLYBCT
= 0
SPI_CR
:SPIEN
= 1
После установки конфигурации, код проверяет, что SPI включена, проверяя флаг SPIENS
.
я выполнить передачу байтов следующим образом:
const short int dataSize = 5;
// Filling array with random data
unsigned char data[dataSize] = {0xA5, 0x34, 0x12, 0x00, 0xFF};
short int i = 0;
volatile unsigned short dummyRead;
SetCS3(); // NPCS3 == PIOA15
while(i-- < dataSize) {
mySPI_Write(data[i]);
while((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
dummyRead = SPI_Read(); // SPI_Read() from Atmel's library
}
ClearCS3();
/**********************************/
void mySPI_Write(unsigned char data) {
while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
AT91C_BASE_SPI0->SPI_TDR = data;
while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TDRE) == 0); // <-- This is where
// the processor hangs, because that the SPI peripheral is disabled
// (SPIENS equals 0), which makes TDRE equal to 0 forever.
}
Вопросы:
- Что вызывает периферийное SPI стал инвалидом на записи в
SPI_TDR
? Должен ли я прокомментировать строку в
SPI_Write()
, которая читает регистрSPI_RDR
?
Средства, 4-й строки в следующем коде: (4-я строка первоначально помечена как комментарий)void SPI_Write(AT91S_SPI *spi, unsigned int npcs, unsigned short data) { // Discard contents of RDR register //volatile unsigned int discard = spi->SPI_RDR; /* Send data */ while ((spi->SPI_SR & AT91C_SPI_TXEMPTY) == 0); spi->SPI_TDR = data | SPI_PCS(npcs); while ((spi->SPI_SR & AT91C_SPI_TDRE) == 0); }
Есть ли что-то не так с выше, что код передает 5 байт данных?
Обратите внимание:
- Линия Num NPCS. 3 - линия GPIO (означает, в режиме PIO) и не управляется контроллером SPI. Я управляю этой линией сам по себе кодом, используя/утверждаю PIN-код ChipSelect # 3 (NPCS3), когда это необходимо. Причина, по которой я это делаю, состоит в том, что эти проблемы возникли, пытаясь позволить контроллеру SPI контролировать этот вывод.
- Я не использовал контроллер PDC/DMA и предпочитаю не использовать его.
Дважды я не переустанавливал периферийное устройство SPI, потому что errata сообщает сбросить его дважды, только если я выполняю сброс - чего я не делаю. Цитируя опечатки:
Если сброс программного обеспечения (SWRST в SPI регистре управления) выполняется, то SPI может не работать правильно (часы включены до выбора микросхемы.)
Проблемы Fix/Обход
Поле регистра управления SPI, SWRST (Сброс программного обеспечения) должно быть записано дважды, чтобы оно было соответствующим образом задано .я заметил, что иногда , если я ставлю задержку перед записью в регистр
SPI_TDR
(вSPI_Write()
), то код работает отлично и коммуникации успешно.
Полезные ссылки:
- AT91SAM7X Series Preliminary.pdf
- ATMEL software package/library
- spi.c from Atmel's library
- spi.h from Atmel's library
Пример инициализации SPI и передача 5 байтов высоко оценен и полезен.
Вы решили этот Дор? Нам было бы интересно узнать, нашли ли вы основную причину. – Bwooce
Я не помню, как я решил проблему. Я думаю, что у меня возникла проблема в процессе инициализации процессорных часов: шаги init были не такими, как записано в таблице данных. – Dor
Примечательно, что этот код не передает пять байтов данных. –