2010-03-18 6 views
2

Моя периферийная периферия AT91SAM7X512 отключается по времени X (меняется X), который я пишу на SPI_TDR. В результате процессор зависает во время цикла, который проверяет флаг TDRE в SPI_SR. Этот цикл while находится в функции SPI_Write(), которая относится к программному обеспечению/библиотеке, предоставляемой ATMEL. Проблема возникает произвольно - иногда все работает нормально, и иногда она терпит неудачу при повторных попытках (attemp = загрузка одного и того же двоичного файла в MCU и запуск программы).SPI периферийное устройство AT91SAM7X512 отключается при записи в SPI_TDR

Конфигурации (определяется в порядке написания):

  1. SPI_MR:
    • MSTR = 1
    • PS = 0
    • PCSDEC = 0
    • PCS = 0111
    • DLYBCS = 0
  2. SPI_CSR[3]:
    • CPOL = 0
    • NCPHA = 1
    • CSAAT = 0
    • BITS = 0000
    • SCBR = 20
    • DLYBS = 0
    • DLYBCT = 0
  3. 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. 
} 

Вопросы:

  1. Что вызывает периферийное SPI стал инвалидом на записи в SPI_TDR?
  2. Должен ли я прокомментировать строку в 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); 
    } 
    
  3. Есть ли что-то не так с выше, что код передает 5 байт данных?

Обратите внимание:

  • Линия Num NPCS. 3 - линия GPIO (означает, в режиме PIO) и не управляется контроллером SPI. Я управляю этой линией сам по себе кодом, используя/утверждаю PIN-код ChipSelect # 3 (NPCS3), когда это необходимо. Причина, по которой я это делаю, состоит в том, что эти проблемы возникли, пытаясь позволить контроллеру SPI контролировать этот вывод.
  • Я не использовал контроллер PDC/DMA и предпочитаю не использовать его.
  • Дважды я не переустанавливал периферийное устройство SPI, потому что errata сообщает сбросить его дважды, только если я выполняю сброс - чего я не делаю. Цитируя опечатки:

    Если сброс программного обеспечения (SWRST в SPI регистре управления) выполняется, то SPI может не работать правильно (часы включены до выбора микросхемы.)
    Проблемы Fix/Обход
    Поле регистра управления SPI, SWRST (Сброс программного обеспечения) должно быть записано дважды, чтобы оно было соответствующим образом задано .

  • я заметил, что иногда , если я ставлю задержку перед записью в регистр SPI_TDRSPI_Write()), то код работает отлично и коммуникации успешно.

Полезные ссылки:

Пример инициализации SPI и передача 5 байтов высоко оценен и полезен.

+0

Вы решили этот Дор? Нам было бы интересно узнать, нашли ли вы основную причину. – Bwooce

+0

Я не помню, как я решил проблему. Я думаю, что у меня возникла проблема в процессе инициализации процессорных часов: шаги init были не такими, как записано в таблице данных. – Dor

+0

Примечательно, что этот код не передает пять байтов данных. –

ответ

1

используется

while(i-- < dataSize) 

декремент целого числа со i, не увеличивая его и доступ к data[i], пока i переполнению положительного значения. Кто знает, что происходит, к какой памяти или регистрам вы обращаетесь? Использование целых чисел без знака обычно лучше, если вам не нужно удерживать отрицательные значения.

Кроме того, вы уже проверяете наличие TXEMPTY, что означает, что данные перемещаются в регистр сдвига и отправляются.Таким образом, вам не нужно также проверять TDRE, что означает, что данные перемещаются в регистр сдвига, но не могут быть отправлены.

Кроме того, я настоятельно рекомендую использовать PDC, если вы не обмениваетесь данными одновременно, что не так, я думаю.