Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: AT91SAM7S128+SPI+PDC=
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
dotprod
Сопрягаю циклонку с самом через spi. Протокол обмена между циклоном и самом жестко завязан на чипсилектах - первый байт после cs упарвляющий/заголовочный. Прогу в циклоне отладил, поганял по самым разным тестам, работает без сбоев. Стал мучать САМину, настроил master-SPI, инициализировал передачу через PDC, начал отлаживать из памяти - сигналы high-NCS0 на осциле проскочили. Запустил из флешены - нету таких.
Поковырялся, изменил прогу на 100% (по моему мнению)-работающий вариант, чипсилекты перестали сниматься вообще blink.gif
Что самое странное- если перед приемом или передачей поставить бряку, то чипселект выпрыгивает в High, и обмен происходит. Такое ощущение что он срабатывает по эстонски.

прога ниже:
Код
#define SPIFRAME    (256)

void cfg_spi(void)
{   AT91PS_SPI pSPI=AT91C_BASE_SPI;

    AT91F_PIO_CfgPeriph(
        AT91C_BASE_PIOA, // PIO controller base address
        AT91C_PA13_MOSI | AT91C_PA14_SPCK | AT91C_PA11_NPCS0 |AT91C_PA12_MISO, // Peripheral A
        0); // Peripheral B
    // spi init
    AT91F_PMC_EnablePeriphClock( AT91C_BASE_PMC, ((unsigned int) 1 << AT91C_ID_SPI));

    AT91F_SPI_Reset (AT91C_BASE_SPI);

    AT91F_SPI_CfgMode( AT91C_BASE_SPI,
                      AT91C_SPI_MSTR | AT91C_SPI_PS_FIXED | AT91C_SPI_FDIV |
                      AT91C_SPI_MODFDIS | ((unsigned int)(0x00<<16) & AT91C_SPI_PCS));

    pSPI->SPI_CSR[0]= AT91C_SPI_BITS_16|
                ((unsigned int) 0x03 <<  8)| // (SPI) Serial Clock Baud Rate
                ((unsigned int) 0x05 << 16)| // (SPI) Delay Before SPCK
                ((unsigned int) 0x00 << 24); // (SPI) Delay Between Consecutive Transfers

    AT91F_PDC_Open (AT91C_BASE_PDC_SPI);

    pSPI->SPI_CR = AT91C_SPI_SPIEN;
}

/*    протокол обмена cpu <=> fpga
    формат обмена : 16-битные слова
    1 слово передача/ прием (пусто)
       15     14     13          12
     | 1 R  | 1 W | Count ena   up/down |  12 adr |

    2 слово - запись по адресу adr / синхро
    3 слово запись по адресу adr+1 / чтение с адреса adr
*/

void txframe( unsigned short address, char uinc, unsigned int count, unsigned short *data)
{ // заголовок
  static volatile unsigned int header;
  unsigned int i;
  // регистр spi
  AT91PS_SPI pSPI=AT91C_BASE_SPI;  AT91PS_PIO pPIO=AT91C_BASE_PIOA;
  AT91PS_PDC pPDC=AT91C_BASE_PDC_SPI;

  // ждем пока успокоится PDC
  while( pPDC->PDC_TCR );
  // (на всякий случай) ждем пока пин чипселекта не станет 1
  while( pSPI->SPI_SR & AT91C_SPI_NSSR==0 );
   // и до тех пор пока не будет окончена пересылка (что 100% дает снятие cs)
  while( pSPI->SPI_SR & AT91C_SPI_TXEMPTY==0 );

  // формирование заголовка
  header=address | (unsigned short)(1<<14) | (unsigned short)(uinc<<13) | (unsigned short)(1<<12);

  AT91F_PDC_DisableTx(pPDC);
  AT91F_PDC_SendFrame( AT91C_BASE_PDC_SPI, (char *) &header, 1, (char *) data, count);
  AT91F_PDC_EnableTx(pPDC);
}

void rxframe( unsigned short address, char uinc, unsigned int count, unsigned short *data)
{ // заголовок
  static volatile unsigned int header;
  static volatile unsigned int trash[20];
  unsigned int i;

  // регистр spi
  AT91PS_SPI pSPI=AT91C_BASE_SPI;
  AT91PS_PIO pPIO=AT91C_BASE_PIOA;
  AT91PS_PDC pPDC=AT91C_BASE_PDC_SPI;

   // дождаться окончания передачи
  while( pPDC->PDC_TCR );
  while( pSPI->SPI_SR & AT91C_SPI_NSSR==0 );
  while( pSPI->SPI_SR & AT91C_SPI_TXEMPTY==0 );
  // чистим на всякий случай регистр приема
  header=pSPI->SPI_RDR;
  // формирование заголовка
  header=address | (unsigned short)(1<<15) | (unsigned short)(uinc<<13) | (unsigned short)(1<<12);
  // добавлено в невменяемом состояни после 4-х часовой отладки
  AT91F_PDC_DisableRx(pPDC); AT91F_PDC_DisableTx(pPDC);
  // установить указатели на прием
  AT91F_PDC_ReceiveFrame( AT91C_BASE_PDC_SPI, (char *) &trash, 2, (char *) data, count);
  // отправка кадра
  AT91F_PDC_SendFrame(AT91C_BASE_PDC_SPI,(char *) &header, 2, (char *) data, count);
  // вот тут тоже
  AT91F_PDC_EnableRx(pPDC);  AT91F_PDC_EnableTx(pPDC);

  // ожидание конца передачи
  while( !AT91F_PDC_IsRxEmpty(AT91C_BASE_PDC_SPI) );
}


static volatile unsigned short trash[SPIFRAME],cash[SPIFRAME];

int main()
{
   //* Begin
  int i,j,k=0;
  float y=0.314f; //здец
  AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1 << AT91C_ID_PIOA );
  // это для отладочного дрыгания ножкой
  AT91F_PIO_CfgOutput( AT91C_BASE_PIOA, AT91C_PIO_PA20);
  AT91F_PIO_SetOutput( AT91C_BASE_PIOA, AT91C_PIO_PA20 );
  
  cfg_spi();

  // тут происходят совершенно непонятные вещи
  while(1)
  {
    for(i=0;i<256;i++,k++)
    { trash[i]=(unsigned short)k; }
    txframe(0x100,1,SPIFRAME,(unsigned short *)trash);
    /*
    ... тут происхотят всякие полезные вычисления числа пи...
    */
    rxframe(0x100,1,SPIFRAME,(unsigned short *)cash);
    j=1;
    for(i=0;i<256;i++)
    { if (trash[i]!=cash[i]) j=0; }
    if (j!=0)
    { if (AT91F_PIO_IsSet(AT91C_BASE_PIOA,AT91C_PIO_PA20))
        AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, AT91C_PIO_PA20 );
      else
        AT91F_PIO_SetOutput( AT91C_BASE_PIOA, AT91C_PIO_PA20 );
    }
  }
}//* End
dotprod
Убрал флаг AT91C_SPI_FDIV, все работает как часы, но почему-то на MCLK/4 blink.gif
Еще один крайне странный глюк - если во время передачи не использовался PDC на прием, то при инициализации дмашки на прием из счетчика принудительно вычитается 1. (Проверено в очень большом цикле, сразу после записи регистр spi pdc rcr уменьшается на едицицу)

Пытаюсь отследить в какой же версии документации на проц исчез флаг AT91C_SPI_FDIV (если внимательно посмотерть - то на его месте нету даже прочерка). sad.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.