Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: AT91SAM7X SPI PDC SD-card
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Колька
Написал свою библиотеку по работе с SD-card. Все работает замечательно. Но есть одно "но". Отправку, прием я сделал без PDC.
Когда мне нужно принять 512 байт, я просто побайтно их последовательно принимаю. Проблема в следующем: настраиваю PDC и в результате приходит "каша". CS-ом дергаю сам. Никто не подскажет в чем может быть проблема? Скорость понижал не помогло. В общем буду рад любому совету.
Колька
Вот к примеру должно прочитатся:

01 02 03 04 05 06 00 00 00

а читается так:

02 04 06 08 0A 0C 0E 00 00


Получается что передача здвинута на бит. Не подскажете в чем может быть проблема?
aaarrr
Вариантов "проблем" может быть много, так что код в студию.
Колька
Функция блочного считывания:
Код
uint8_t datablock_read(uint8_t* buff, uint32_t btr) {
  uint8_t token;

  uint32_t time = OSTime;

  while (1) {
    token = SPI_Read(0xFF);
    if (token != 0xFF)
      break;
    if ((OSTime - time) > 100)
      break;
  }

  if (token != 0xFE)
    return 0;

  #if USE_DMA        
    SPI_Read_PDC(buff, btr);
  #else
    do {
      SPI_Read(buff++);
    } while (btr -= 1);
  #endif
  SPI_Read(0xFF);
  SPI_Read(0xFF);

  return 1;
}

***** *

unsigned short SPI_Read(PSPI self, unsigned short data) {

  while ((BASE_SPI->SPI_SR &AT91C_SPI_TDRE) == 0)
;

  self->BASE_SPI->SPI_TDR = (data &0xFFFF);


  while (0 == (self->BASE_SPI->SPI_SR &AT91C_SPI_RDRF))
;

  return ((self->BASE_SPI->SPI_RDR) &0xFFFF);
}


short SPI_Read_PDC(PSPI self, void* data, unsigned short count) {

  self->BASE_SPI->SPI_RDR;
  self->BASE_SPI->SPI_SR;

  self->BASE_SPI_PDC->PDC_RPR = (unsigned int)data;
  self->BASE_SPI_PDC->PDC_RCR = count;

  self->BASE_SPI_PDC->PDC_PTCR = AT91C_PDC_RXTEN;
  self->BASE_SPI->SPI_IER = (AT91C_SPI_ENDRX);

  if (SPI_Send_PDC(self, dma_dummy, count) == count) {
    xSemaphoreTake(self->RXSemaphore, timeout);
  }

  self->BASE_SPI->SPI_IDR = AT91C_SPI_ENDRX;
  self->BASE_SPI_PDC->PDC_RCR = 0;

  (unsigned long)self->BASE_SPI->SPI_SR;
  (unsigned long)self->BASE_SPI->SPI_RDR;

  self->BASE_SPI_PDC->PDC_PTCR = AT91C_PDC_RXTDIS;

  unsigned short res = count - (self->BASE_SPI_PDC->PDC_RCR);

  return res;
}


dma_dummy - масив с 0xFF значениями. SPI_Send_PDC - запись, один в один такая же как и чтение, кроме регистров иннициализации отправки, а логика такая же поэтому не привожу.
Коэффициент деления: 2, при иннициализации 200. Параметры: AT91C_SPI_CPOL | AT91C_SPI_BITS_8

В общем при "#define USE_DMA 0" работает, а при "#define USE_DMA 1" нет sad.gif
Где ошибка у меня ошибка? Не подскажите?
aaarrr
Цитата(Колька @ Sep 22 2009, 21:11) *
SPI_Send_PDC - запись, один в один такая же как и чтение, кроме регистров иннициализации отправки, а логика такая же поэтому не привожу.

Напрасно, ибо вот это абсолютно не понятно:
Код
  if (SPI_Send_PDC(self, dma_dummy, count) == count) {
    xSemaphoreTake(self->RXSemaphore, timeout);
  }

Кто, где, когда и при каких условиях это семафор ставит?
Колька
Мне кажется дело не в том. Вот заменил функцию SPI_Read_PDC, что бы было более понятно, результат тот жеsad.gif((
Код
short SPI_Read_PDC(PSPI self, void* data, unsigned short count) {

    PSPI_BASE->SPI_RPR = (UINT)buff; // destination address
    PSPI_BASE->SPI_RCR = btr; // number of frames (here: frame=byte)
    // SPI PDC TX buffer (dummy bytes):
    PSPI_BASE->SPI_TPR = (UINT)dma_dummy; // source address
    PSPI_BASE->SPI_TCR = btr; // number of frames (here: frame=byte)
    
    PSPI_BASE->SPI_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTEN;
        
    while( !( (PSPI_BASE->SPI_SR) & AT91C_SPI_RXBUFF ) ) {
        // wait for RX Buffer Full (counters 0)
    }
}

Проблемы не могут идти от каких-то особенностей карты или PDC-режима?
aaarrr
Цитата(Колька @ Sep 22 2009, 23:29) *
Проблемы не могут идти от каких-то особенностей карты или PDC-режима?

Да нет там особенностей никаких, функция у Вас вполне честная. Разве что отключением SPI можно получить какой-нибудь glitch на SCK и, как следствие, смещение на бит.
Колька
Пока сам для себя причину не выяснил, так как ещё новичек, но вот так работает:

Цитата
short SPI_Read_PDC(PSPI self, void* data, unsigned short count) {
PSPI_BASE->SPI_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;

PSPI_BASE->SPI_RPR = (UINT)buff; // destination address
PSPI_BASE->SPI_RCR = btr; // number of frames (here: frame=byte)
// SPI PDC TX buffer (dummy bytes):
PSPI_BASE->SPI_TPR = (UINT)dma_dummy; // source address
PSPI_BASE->SPI_TCR = btr; // number of frames (here: frame=byte)

PSPI_BASE->SPI_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTEN;

while( !( (PSPI_BASE->SPI_SR) & AT91C_SPI_RXBUFF ) ) {
// wait for RX Buffer Full (counters 0)
}
}
aaarrr
Теоретически такое возможно, если PDC использовался ранее. Но сдвига данных на бит никогда не встречал.
Колька
Жаль что осциллографа нет что бы проверить как сигнал формируется. Но примерно сам для себя причину неполадок я понял. Всем спасибо.
Колька
Попутный вопрос возник. У всех ли SD-картах размер сектора равняется 512?
aaarrr
По первой спецификации все обязаны поддерживать блоки в 512 байт:
Цитата
It is a mandatory requirement that SD Memory Card shall have a capability to transfer blocks of 512 Bytes.
...
A card supporting block write shall always be able to accept a block of data defined by WRITE_BL_LEN and its
512bytes derivatives (for example: If write block length=1024bytes then write blocks of 1024 and 512bytes are supported).


Во второй спецификации размер блока строго фиксирован на 512.
head_sk
CMD16 - Selects a block length in bytes for all following block commands (read & write).

Как уже было упомянуто размер блока 512 фиксировано. Но в своей программе я выполняю данную команду с параметром 512, для совместимости со всеми карточками.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.