Контроллер работает в Master режиме, прием/передача происходит с помощью PDC. Факт окончания операций записи/чтения определяется по прерываниям.
Проблема в следующем: при приеме данные смещаются на один байт. Т.е я программирую PDC на прием/передачу 3 байта данных, но в применом буфере полученные данные оказываются смещенными на один байт. Т.е байт, который должен находится в буфере со смещением 1 реально размещен со смещением 2. Причем смотрю осцилографом - ответ от микросхемы честный, начиная с 9-го клока шины данные добросовестно передаются. Т.е байт данных должен попасть в буфер со смещением 1 , а на практике попадает по смещению 2.
Инициализация SPI0 следующая:
Код
// Конфигурирование PIO на предмет включения перефирии SPI0 к выводам порта A
AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA,
AT91C_PA12_SPI0_NPCS0 | AT91C_PA16_SPI0_MISO | AT91C_PA17_SPI0_MOSI | AT91C_PA18_SPI0_SPCK,0);
// Включение клоков для SPI0
AT91F_SPI0_CfgPMC();
// Конфигурирование SPI0
AT91F_SPI_CfgMode(AT91C_BASE_SPI0, AT91C_SPI_MSTR | AT91C_SPI_PS_FIXED); // Master, CS Fixed not decoded, Mode Fault Detection Enable, PCS=0 (NCS0 Active)
AT91F_SPI_CfgCs(AT91C_BASE_SPI0, 0, AT91C_SPI_NCPHA | AT91C_SPI_BITS_8 | (16<<8)); // 8 бит, частота SPCK boudrate=MCK/16 = 3 Mhz
// Конфигурирования прерываний по SPI
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
AT91C_ID_SPI0,
AT91C_AIC_PRIOR_HIGHEST,
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
SPI0_Interrupt);
// AT91F_SPI_EnableIt(AT91C_BASE_SPI0, AT91C_SPI_ENDTX);
// Включение прерываний
AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SPI0);
// Включение SPI0
AT91F_SPI_Enable(AT91C_BASE_SPI0);
AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA,
AT91C_PA12_SPI0_NPCS0 | AT91C_PA16_SPI0_MISO | AT91C_PA17_SPI0_MOSI | AT91C_PA18_SPI0_SPCK,0);
// Включение клоков для SPI0
AT91F_SPI0_CfgPMC();
// Конфигурирование SPI0
AT91F_SPI_CfgMode(AT91C_BASE_SPI0, AT91C_SPI_MSTR | AT91C_SPI_PS_FIXED); // Master, CS Fixed not decoded, Mode Fault Detection Enable, PCS=0 (NCS0 Active)
AT91F_SPI_CfgCs(AT91C_BASE_SPI0, 0, AT91C_SPI_NCPHA | AT91C_SPI_BITS_8 | (16<<8)); // 8 бит, частота SPCK boudrate=MCK/16 = 3 Mhz
// Конфигурирования прерываний по SPI
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
AT91C_ID_SPI0,
AT91C_AIC_PRIOR_HIGHEST,
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
SPI0_Interrupt);
// AT91F_SPI_EnableIt(AT91C_BASE_SPI0, AT91C_SPI_ENDTX);
// Включение прерываний
AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SPI0);
// Включение SPI0
AT91F_SPI_Enable(AT91C_BASE_SPI0);
Сам код для приема- передчаи данных по SPI:
Код
CmdSndBuf[0]=CS5368_SPICMD_WRITE;
CmdSndBuf[1]=Addr;
// Настройка PDC для SPI
*AT91C_SPI0_PTCR= AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS; // Если были PDC трансферы в текущий момент - отключаем
*AT91C_SPI0_TPR= (unsigned)CmdSndBuf;
*AT91C_SPI0_TCR= 2;
*AT91C_SPI0_TNCR= 0;
CmdSndFlag=false;
// Запуск процесса отправки команды к АЦП cs5368
*AT91C_SPI0_PTCR= AT91C_PDC_TXTEN;
AT91F_SPI_EnableIt(AT91C_BASE_SPI0, AT91C_SPI_ENDTX);
// Ожидание выполнения операции
while (!CmdSndFlag);
for (int zz=0;zz<20;zz++)
__no_operation();
// Подготовка буфера для отправки команды чтения данных
CmdSndBuf[0]=CS5368_SPICMD_READ;
CmdSndBuf[1]=0;
CmdSndBuf[2]=0;
// Настройка PDC для SPI
*AT91C_SPI0_PTCR= AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS;
*AT91C_SPI0_RPR= (unsigned)CmdRcvBuf;
*AT91C_SPI0_RCR= 3;
*AT91C_SPI0_RNCR= 0;
*AT91C_SPI0_TPR= (unsigned)CmdSndBuf;
*AT91C_SPI0_TCR= 3;
*AT91C_SPI0_TNCR= 0;
CmdRcvFlag=false;
// Запуск процесса отправки команды к АЦП cs5368
*AT91C_SPI0_PTCR= AT91C_PDC_TXTEN | AT91C_PDC_RXTEN;
AT91F_SPI_EnableIt(AT91C_BASE_SPI0, AT91C_SPI_ENDRX);
// Ожидание выполнения операции
while (!CmdRcvFlag);
CmdSndBuf[1]=Addr;
// Настройка PDC для SPI
*AT91C_SPI0_PTCR= AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS; // Если были PDC трансферы в текущий момент - отключаем
*AT91C_SPI0_TPR= (unsigned)CmdSndBuf;
*AT91C_SPI0_TCR= 2;
*AT91C_SPI0_TNCR= 0;
CmdSndFlag=false;
// Запуск процесса отправки команды к АЦП cs5368
*AT91C_SPI0_PTCR= AT91C_PDC_TXTEN;
AT91F_SPI_EnableIt(AT91C_BASE_SPI0, AT91C_SPI_ENDTX);
// Ожидание выполнения операции
while (!CmdSndFlag);
for (int zz=0;zz<20;zz++)
__no_operation();
// Подготовка буфера для отправки команды чтения данных
CmdSndBuf[0]=CS5368_SPICMD_READ;
CmdSndBuf[1]=0;
CmdSndBuf[2]=0;
// Настройка PDC для SPI
*AT91C_SPI0_PTCR= AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS;
*AT91C_SPI0_RPR= (unsigned)CmdRcvBuf;
*AT91C_SPI0_RCR= 3;
*AT91C_SPI0_RNCR= 0;
*AT91C_SPI0_TPR= (unsigned)CmdSndBuf;
*AT91C_SPI0_TCR= 3;
*AT91C_SPI0_TNCR= 0;
CmdRcvFlag=false;
// Запуск процесса отправки команды к АЦП cs5368
*AT91C_SPI0_PTCR= AT91C_PDC_TXTEN | AT91C_PDC_RXTEN;
AT91F_SPI_EnableIt(AT91C_BASE_SPI0, AT91C_SPI_ENDRX);
// Ожидание выполнения операции
while (!CmdRcvFlag);
Обработка прерываний SPI:
Код
//---------------------------------------------------------------------
// Обработчик прерывания от SPI0
void SPI0_Interrupt()
{ if (*AT91C_SPI0_SR & AT91C_SPI_ENDTX)
{ CmdSndFlag=true;
AT91F_SPI_DisableIt(AT91C_BASE_SPI0, AT91C_SPI_ENDTX);
}
if (*AT91C_SPI0_SR & AT91C_SPI_ENDRX)
{ CmdRcvFlag=true;
AT91F_SPI_DisableIt(AT91C_BASE_SPI0, AT91C_SPI_ENDRX);
}
*AT91C_AIC_EOICR=AT91C_ID_SPI0;
}
// Обработчик прерывания от SPI0
void SPI0_Interrupt()
{ if (*AT91C_SPI0_SR & AT91C_SPI_ENDTX)
{ CmdSndFlag=true;
AT91F_SPI_DisableIt(AT91C_BASE_SPI0, AT91C_SPI_ENDTX);
}
if (*AT91C_SPI0_SR & AT91C_SPI_ENDRX)
{ CmdRcvFlag=true;
AT91F_SPI_DisableIt(AT91C_BASE_SPI0, AT91C_SPI_ENDRX);
}
*AT91C_AIC_EOICR=AT91C_ID_SPI0;
}
В errata по данной ситуации никаких упоминаний нет. Не могу понять, где я глючу ?