Волосатые руки наконец дотянулись до SPI. Оказалось теперь не срабатывает бит LASTXFER и CS1 после окончания передачи лежит в нуле и не дышит. И это на двух платах, сигналы все в норме.
Код инициализации вот такой:
CODE
/* SPI reset */
//* Disable all interrupts
AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF;
//* Reset all the Chip Select register
AT91C_BASE_SPI->SPI_CSR[0] = 0;
AT91C_BASE_SPI->SPI_CSR[1] = 0;
AT91C_BASE_SPI->SPI_CSR[2] = 0;
AT91C_BASE_SPI->SPI_CSR[3] = 0;
//* Reset the SPI mode
AT91C_BASE_SPI->SPI_MR = 0 ;
//* Disable the RX and TX PDC transfer requests
AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
//* Reset all Counter register Next buffer first
AT91C_BASE_SPI->SPI_TNPR = 0;
AT91C_BASE_SPI->SPI_TNCR = 0;
AT91C_BASE_SPI->SPI_RNPR = 0;
AT91C_BASE_SPI->SPI_TNCR = 0;
AT91C_BASE_SPI->SPI_TPR = 0;
AT91C_BASE_SPI->SPI_TCR = 0;
AT91C_BASE_SPI->SPI_RPR = 0;
AT91C_BASE_SPI->SPI_RCR = 0;
//* Disable receiver and transmitter and stop any activity immediately
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST | AT91C_SPI_SPIDIS;
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST | AT91C_SPI_SPIDIS;
/* Configure PIOs */
AT91C_BASE_PIOA->PIO_PDR = (unsigned int) AT91C_PA13_MOSI
|(unsigned int) AT91C_PA14_SPCK
|(unsigned int) AT91C_PA12_MISO;
AT91C_BASE_PIOA->PIO_ASR = (unsigned int) AT91C_PA13_MOSI
|(unsigned int) AT91C_PA14_SPCK
|(unsigned int) AT91C_PA12_MISO;
/* аппаратный сигнал CS для акселерометра */
AT91C_BASE_PIOA->PIO_PDR = (unsigned int) AT91C_PA31_NPCS1;
AT91C_BASE_PIOA->PIO_ASR = (unsigned int) AT91C_PA31_NPCS1;
/* Включаем модуль SPI в PMC */
AT91C_BASE_PMC->PMC_PCER = (unsigned int) 1 << AT91C_ID_SPI;
/* Кофигурируем SPI в режиме MASTER без CS */
AT91C_BASE_SPI->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PCS;
/* Конфигурируем CS */
/* Конфигурируем канал SPI для DF AT45DBXXX */
AT91C_BASE_SPI->SPI_CSR[0] = AT91C_SPI_BITS_8 /* отрицательная полярность тактов */
| AT91C_SPI_CPOL
| ((16 << 8) & AT91C_SPI_SCBR); /* делитель MCK */
/* конфигурируем канал 1 для акселерометра ADXL345 4 MHz максимум */
AT91C_BASE_SPI->SPI_CSR[1] = AT91C_SPI_BITS_8
| AT91C_SPI_CPOL /* отрицательная полярность тактов */
| AT91C_SPI_CSAAT /* не поднимать CS после предачи слова */
| ((16 << 8) & AT91C_SPI_SCBR) /* делитель MCK */
| ((24 << 16) & AT91C_SPI_DLYBS); /* пауза перед подачей тактирующего сигнала */
/* Включаем SPI */
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
Работа с SPI вкратце выглядит вот так:
CODE
/* ЗАПИСЬ в регистр */
/* дожидаемся окончания передачи */
while(!(AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY))
{ continue; }
/* выбираем указанный чип-селект */
AT91C_BASE_SPI->SPI_MR &= 0xFFF0FFFF;
pcs_device = (~(1 << chip_select));
AT91C_BASE_SPI->SPI_MR |= ( (pcs_device << 16) & AT91C_SPI_PCS );
/* отсылаем слово */
AT91C_BASE_SPI->SPI_TDR = send_word | (( pcs_device << 16) & AT91C_SPI_TPCS);
/* ЧТЕНИЕ из регистра */
/* дожидаемся окончания передачи */
while(!(AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY))
{ continue; }
/* убираем последствия предидущих транзакций */
temp = AT91C_BASE_SPI->SPI_RDR;
/* выбираем указанный CS */
AT91C_BASE_SPI->SPI_MR &= 0xFFF0FFFF;
pcs_device = (~(1 << chip_select));
AT91C_BASE_SPI->SPI_MR |= ( (pcs_device << 16) & AT91C_SPI_PCS );
/* для корректной работы нужно записывать нули */
AT91C_BASE_SPI->SPI_TDR = 0x0000 | ((pcs_device << 16) & AT91C_SPI_TPCS) | AT91C_SPI_LASTXFER;
/* дожидаемся окончания передачи */
while(!(AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF))
{ continue; }
temp = AT91C_BASE_SPI->SPI_RDR;
После последней транзыкции наблюдаю печальное положение вещей на CS1, данные вроде такие как надо, с тактированием точно все ОК. На старых ревизиях A и B все работает как надо. Никаких упоминаний в эррате о таком поведении конечно не нашел.
Продолжаю изучать улучшенный кристалл за 7 баксов.
Сообщение отредактировал IgorKossak - Dec 21 2011, 10:05
Причина редактирования: [codebox] !!!
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.