Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: глюки с SPI PDC AT91SAM7A3
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
shrek
Добрый вечер.
Суть проблемы вот в чем.
Хотелось написать простенький код для чтения записи байтов во флэш контроллера nRF24LE1 по интерфейсу программирования SPI.
Решил заморочиться с PDC. Так вот сначала (при чтении данных из флэш) надо отправить 1 байт (команда), затем 2 байта (адресс) потом, тактируя, контроллер выдает байты из флэш, инкрементируя свой счетчик адреса.
Делаю так:
- Предварительно проинициализировал стек, генераторную часть, контроллер прерываний, контроллер SPI, разрешив соотвествующие ноги для контроллера.
(пишу из дома, код на работе, собственно это надо для работы, возможности кита для nRF24LE1 немного ограничены для наших задач)
- Инициализирую часть PDC для SPI, назначил 4 буфера, 2 для команд по 3 байта (на прием и передачу), 2 для данных по 8 байт (на прием и передачу.
- Прописал число байт для PDC_RPR, PDC_RCR, PDC_RNPR, PDC_RNCR, PDC_TPR, PDC_TCR, PDC_TNPR, PDC_TNCR.
Запускаю...
В общем первые 2 байта контроллер передал команду (0х03 чтение флэш) старший байт адреса и ... дальше он передал 0хFF (адресс 0х0100). Предварительно я проинициализировал переменные все и записал все в буфер.
Ну соответственно контроллер отдал арму данные из флэш по адресу 0х01FF.
Дальше пробую просто с 2 буферами 1 на чтение 2 на передачу по 11 байт каждый. Первый байт буфера на передачу соотвественно команда 0x03 второй и третий адрес 0х0100.
Смотрел все по осцилу. Во втором случае нормально передалось. Прочитал байты из флэш, сравнил, совпадают (ну почти... почему-то nRF24LE1 младший бит байта не держит до спада, по фронту сохранение бита по спаду изменение, ну это уже другая история).
Всегда работал с PDC такого никогда не было правда я до этого не использовал next буфер))) rolleyes.gif
shrek
Привожу код:
Кусок кода инициализации SPI:
Код
//---Конфигурация SPI-----------------------------------------------------------
     AT91C_BASE_PMC  -> PMC_PCER    = AT91C_ID_SPI0 | AT91C_ID_PIOA;
     AT91C_BASE_PIOA -> PIO_PER     = AT91C_PIO_PA18 | AT91C_PIO_PA19;
     AT91C_BASE_PIOA -> PIO_SODR    = AT91C_PIO_PA18;
     AT91C_BASE_PIOA -> PIO_CODR    = AT91C_PIO_PA19;
     AT91C_BASE_PIOA -> PIO_OER     = AT91C_PIO_PA18 | AT91C_PIO_PA19;
     AT91C_BASE_PIOA -> PIO_PDR     = AT91C_PIO_PA14 | AT91C_PIO_PA15 | AT91C_PIO_PA16 | AT91C_PIO_PA17;
     AT91C_BASE_PIOA -> PIO_ASR     = AT91C_PA14_NPCS03 | AT91C_PA15_MISO0 | AT91C_PA16_MOSI0 | AT91C_PA17_SPCK0;
     AT91C_BASE_SPI0 -> SPI_CR      = AT91C_SPI_SWRST | AT91C_SPI_SPIDIS;
     AT91C_BASE_SPI0 -> SPI_MR      = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | (0xF << 16);
     AT91C_BASE_SPI0 -> SPI_CSR[3]  = AT91C_SPI_BITS_8 | AT91C_SPI_NCPHA | (32 << 8) | (32 << 16) | (4 << 24);
     AT91C_BASE_SPI0 -> SPI_IDR     = AT91C_SPI_ALL_INT;
     AT91C_BASE_SPI0 -> SPI_IER     = AT91C_SPI_ENDRX;


рабочий вариант main:
Код
void main()
     {
     i = 11;
     while (i--)
          {
          flash_RX[i] = 0;
          flash_TX[i] = 0;
          }
    
     addr = (unsigned short int *) (flash_TX + 1);
     com = flash_TX;
     *addr = 0x0001;
     *com = 0x3;
    
     AT91C_BASE_SPI0 -> SPI_CR   = AT91C_SPI_SPIEN;
     AT91C_BASE_PIOA -> PIO_SODR = AT91C_PIO_PA19;
     delay(100);
     AT91C_BASE_PIOA -> PIO_CODR = AT91C_PIO_PA18;
     delay(100);
     AT91C_BASE_PIOA -> PIO_SODR = AT91C_PIO_PA18;
     delay(10000);
    
     AT91C_BASE_PDC_SPI0 -> PDC_RPR    = (unsigned int) flash_RX;
     AT91C_BASE_PDC_SPI0 -> PDC_RCR    = 11;
     AT91C_BASE_PDC_SPI0 -> PDC_RNCR   = 0;
     AT91C_BASE_PDC_SPI0 -> PDC_TPR    = (unsigned int) flash_TX;
     AT91C_BASE_PDC_SPI0 -> PDC_TCR    = 11;
     AT91C_BASE_PDC_SPI0 -> PDC_TNCR   = 0;
     AT91C_BASE_SPI0     -> SPI_MR     = AT91C_SPI_MSTR | AT91C_SPI_DLYBCS | AT91C_SPI_MODFDIS | (0x7 << 16);
     AT91C_BASE_PDC_SPI0 -> PDC_PTCR   = AT91C_PDC_TXTEN | AT91C_PDC_RXTEN;
    
     while (1);
     }


Вариант, который пытался реализовать:
Код
void main()
     {
     i = 8;
     while (i--)
          {
          flash_RX[i] = 0;
          flash_TX[i] = 0;
          }
    
     addr = (unsigned short int *) (com_TX + 1);
     com = com_TX;
     *addr = 0x0001;
     *com = 0x3;
    
     AT91C_BASE_SPI0 -> SPI_CR   = AT91C_SPI_SPIEN;
     AT91C_BASE_PIOA -> PIO_SODR = AT91C_PIO_PA19;
     delay(100);
     AT91C_BASE_PIOA -> PIO_CODR = AT91C_PIO_PA18;
     delay(100);
     AT91C_BASE_PIOA -> PIO_SODR = AT91C_PIO_PA18;
     delay(10000);
    
     AT91C_BASE_PDC_SPI0 -> PDC_RPR    = (unsigned int) com_RX;
     AT91C_BASE_PDC_SPI0 -> PDC_RCR    = 3;
     AT91C_BASE_PDC_SPI0 -> PDC_RNPR   = (unsigned int) flash_RX;
     AT91C_BASE_PDC_SPI0 -> PDC_RNCR   = 8;
     AT91C_BASE_PDC_SPI0 -> PDC_TPR    = (unsigned int) com_TX;
     AT91C_BASE_PDC_SPI0 -> PDC_TCR    = 3;
     AT91C_BASE_PDC_SPI0 -> PDC_TNPR   = (unsigned int) flash_RX;
     AT91C_BASE_PDC_SPI0 -> PDC_TNCR   = 8;
     AT91C_BASE_SPI0     -> SPI_MR     = AT91C_SPI_MSTR | AT91C_SPI_DLYBCS | AT91C_SPI_MODFDIS | (0x7 << 16);
     AT91C_BASE_PDC_SPI0 -> PDC_PTCR   = AT91C_PDC_TXTEN | AT91C_PDC_RXTEN;
    
     while (1);
     }


Все вроде просто. Запустил в отладке, посмотрел что пришло от nRF24LE1.
В errata упоминания по этому поводу вроде как не нашел... 05.gif
shrek
Собственно нашлось решение.
Я инициализировал для мастера только SPI_CSR[3].
Как подтвердилось опытным путем с fixed периферией надо инициализировать все... SPI_CSR[0], SPI_CSR[1], SPI_CSR[2], SPI_CSR[3]. Тогда PDC читает данные из буфера корректно.
Причем ножки NPCS0х можно ставить на выход какие нужно.
В принципе тему можно считать закрытой.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.