HOUSEHOUSE 0 10 мая, 2010 Опубликовано 10 мая, 2010 · Жалоба Здравствуйте. Пишу код для приема данных по SPI (используется для связи с SD-картой). Что-то пока не работет. uint8_t SPI_Recv(uint8_t *buff, uint32_t size) { *pDMA5_PERIPHERAL_MAP = 0x5000; *pSPI_CTL &= ~SPE; *pDMA5_CONFIG = WDSIZE_8 | WNR; *pDMA5_START_ADDR = (void *)buff; *pDMA5_X_COUNT = size; *pDMA5_X_MODIFY = 1; *pDMA5_CONFIG = (*pDMA5_CONFIG | DMAEN); *pSPI_FLG = FLS; *pSPI_BAUD = 4; *pSPI_CTL = 0x2 | MSTR; *pSPI_CTL |= SPE; // wait until dma transfers for spi are finished sleep(50); *pDMA5_CONFIG = (*pDMA5_CONFIG & ~DMAEN); *pSPI_CTL &= ~SPE; return size; } Проблема в том, что не принимается первый байт в посылке. В чем ошибка в моем коде? Если все это хазяйство заменить на uint8_t SPI_Recv(uint8_t *buff, uint32_t size) { uint32_t i; for(i = 0; i < size; i++) buff[i] = SPI_SendByte(0xFF); return size; } uint8_t SPI_SendByte(uint8_t outgoing) { uint8_t incoming = 0; while(!(*pSPI_STAT & SPIF)); *pSPI_TDBR = outgoing; while(*pSPI_STAT & RXS) incoming = *pSPI_RDBR; return(incoming); } то все отлично работает, далее подымается драйвер FAT32. Но вот только когда заменяю функцию на использование DMA сразу глюки, теряется 1 байт. В чем ошибка? Кто-то может поделится рабочим куском кода для приема по SPI с использованием DMA? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gradient 1 11 мая, 2010 Опубликовано 11 мая, 2010 · Жалоба По идее, (в даташите написано) первый байт не должен использоваться как информационный. Попробуйте почистить FIFO перед принятием блока и затем установить флаг - "буфер полный". И зачем Вы 2 раза обращатесь к *pSPI_CTL ? Настройка и запуск - всё делается в одной команде. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HOUSEHOUSE 0 11 мая, 2010 Опубликовано 11 мая, 2010 · Жалоба По идее, (в даташите написано) первый байт не должен использоваться как информационный. А как его использовать не как информационный, если SD-карта возвращает ответ уже на первый байт (если заменить DMA на не DMA, функции я указал, все работает)??? Попробуйте почистить FIFO перед принятием блокаЭто сделал не помогло. и затем установить флаг - "буфер полный".Не понял, не подскажите как это сделать? И зачем Вы 2 раза обращатесь к *pSPI_CTL ? Настройка и запуск - всё делается в одной команде. Это тоже исправил. Пока после предложенных изменений не заработало. При чем функция отправки с использованием DMA работает правильно. Т.е. если отправку делать по DMA, а когда нужен прием не использовать DMA, то все работает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gradient 1 11 мая, 2010 Опубликовано 11 мая, 2010 · Жалоба 1. В случае с аппаратными устройствами, Вы абсолютно правы. Пропускать первый байт нельзя. 2. установка флага: *pSPI_CTL = SZ; //Stop SPI *pSPI_TDBR = 0; //Set Buffer full Смысл, чтоб при поступлении нового символа в полный буфер, контроллер DMA сделал транзакцию в память. И ещё, есть смысл убрать флаг WDSIZE_8, он всё равно = 0. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HOUSEHOUSE 0 11 мая, 2010 Опубликовано 11 мая, 2010 · Жалоба *pSPI_CTL = SZ; //Stop SPI Что-то я торможу, судя с документации SZ означает когда SPI_TDBR пуст, производится отправка нуля, а если не установлен то передача последнего слова. Поэтому что-то не понял. При общении с SD-картой, процессор является мастером, и при приема данных я долже отправлять код 0xFF иначе SD-карта это примет за ошибку. Поэтому установка этого флага приведек к неработоспособности работы функций даже без DMA. *pSPI_TDBR = 0; //Set Buffer full А эта запись, яя не понимаю что она очищает. Записывая сюда ноль, мы подразумеваем что следующая отправка (в интерфейсе SPI для того что бы что-то принять нужно отправить, для мастера) будет содержать байт ноль, что для нас тоже критично, если процессор принимает данные с SD-карту он должен отправлять 0xFF. Ещё будут какие-то предположения? Наверняка же кто-то уже реализовывал отправку/прием данных по SPI с использованием DMA, да и очень возможно что даже для связки с SD-картой. Так если не жалко не поделитесь кодом, именно двуня функциями, иннициализацией и приемо/отправкой??? Заранее благодарен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gradient 1 11 мая, 2010 Опубликовано 11 мая, 2010 · Жалоба Тогда под Ваш случай в SPI_TDBR нужного вписать 0xFF, когда Вы принимаете по DMA этот код и будет передаваться карте. Я просто не сталкивался вплотную с SD протоколом, а использовал SPI DMA под свой. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HOUSEHOUSE 0 11 мая, 2010 Опубликовано 11 мая, 2010 · Жалоба Тогда под Ваш случай в SPI_TDBR нужного вписать 0xFF, когда Вы принимаете по DMA этот код и будет передаваться карте.Я попробывал использовать, но все равно 1 байт теряется :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gradient 1 11 мая, 2010 Опубликовано 11 мая, 2010 · Жалоба А в смысле байт "теряется"? Его просто нет или там какой-то случайный мусор от предидущего пакета? Или константное значение? Что в знакоместе по адресу DMA_Buff[0]? Куда попадает байт номер 2? Посмотрите, потому что без инфо сложно подсказать где ковырять. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HOUSEHOUSE 0 11 мая, 2010 Опубликовано 11 мая, 2010 · Жалоба А в смысле байт "теряется"? Его просто нет или там какой-то случайный мусор от предидущего пакета? Или константное значение? Что в знакоместе по адресу DMA_Buff[0]? Куда попадает байт номер 2? Посмотрите, потому что без инфо сложно подсказать где ковырять. Ну к примеру должно быть "0x00, 0x00, 0x01, 0xAA", а получаю я "0х00, 0х01, 0хAA, 0xFF". Или нужно "0x80, 0xFF. 0x80, 0x00" а я получаю "0xFF, 0x80, 0x00, 0xFF" перед считыванием в буфер заносил мусор что определить что данные реально записываются а не остаются. Как видно данные сдвигаются влево, а последний байт FF. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gradient 1 11 мая, 2010 Опубликовано 11 мая, 2010 · Жалоба Хм... завтра на работе потестю у себя на плате. А пока, предложение одно, заголовок протокола обслуживать по прерываниям, а тело страницы памяти пересылать по ДМА. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HOUSEHOUSE 0 11 мая, 2010 Опубликовано 11 мая, 2010 · Жалоба А пока, предложение одно, заголовок протокола обслуживать по прерываниям, а тело страницы памяти пересылать по ДМА. А вы бы не могли по подробнее, что именно по прерываниям а что с DMA я не понял. Главное функция отправки uint8_t SPI_Send(const uint8_t *buff, uint32_t size) { *pDMA5_PERIPHERAL_MAP = 0x5000; while(!(*pSPI_STAT & SPIF)); *pSPI_CTL = 0; *pDMA5_CONFIG = WDSIZE_8 | RESTART; *pDMA5_START_ADDR = (void *)buff; *pDMA5_X_COUNT = size; *pDMA5_X_MODIFY = 1; *pDMA5_CONFIG = (*pDMA5_CONFIG | DMAEN); *pSPI_FLG = FLS; *pSPI_BAUD = 4; *pSPI_CTL = 0x3 | MSTR | SPE; while (*pDMA5_IRQ_STATUS & DMA_RUN); // wait for DMA to complete Check_TXS: while (*pSPI_STAT & TXS); if (*pSPI_STAT & TXS) goto Check_TXS; while (!(*pSPI_STAT & SPIF)); *pDMA5_CONFIG = (*pDMA5_CONFIG & ~DMAEN); SPI_HardwareInitial(4); return size; } А вот принимать я принимаю вот так: uint8_t SPI_Recv(uint8_t *buff, uint32_t size) { uint32_t i; for(i = 0; i < size; i++) buff[i] = SPI_SendByte(0xFF); return size; } uint8_t SPI_SendByte(uint8_t outgoing) { uint8_t incoming = 0; while(!(*pSPI_STAT & SPIF)); *pSPI_TDBR = outgoing; while(*pSPI_STAT & RXS) incoming = *pSPI_RDBR; return(incoming); } Кстати когда нужно отправить один байт я тоже использую SPI_SendByte. В вот такой связке все работает, поднялась библиотека FAT32 от чана. Как только заменяю на прием с помощью DMA сразу глюки, последняя версия этой функции такая. uint8_t SPI_Recv(uint8_t *buff, uint32_t size) { *pDMA5_PERIPHERAL_MAP = 0x5000; while(!(*pSPI_STAT & SPIF)); *pSPI_CTL = 0; sleep(10); *pDMA5_CONFIG = WDSIZE_8 | WNR | RESTART; *pDMA5_START_ADDR = (void *)buff; *pDMA5_X_COUNT = size; *pDMA5_X_MODIFY = 1; *pDMA5_CONFIG = (*pDMA5_CONFIG | DMAEN); *pSPI_FLG = 0xEF | FLS; *pSPI_BAUD = 4; *pSPI_TDBR = 0xFF; *pSPI_CTL = 0x2 | MSTR | EMISO | GM | SPE; // wait until dma transfers for spi are finished sleep(50); // turn off DMA *pDMA5_CONFIG = (*pDMA5_CONFIG & ~DMAEN); SPI_HardwareInitial(4); return size; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gradient 1 11 мая, 2010 Опубликовано 11 мая, 2010 · Жалоба Чтоб поподробнее, мне нужно хотя-бы прочитать как SD карта работает. На моей плате только межпроцессорный обмен и чтение флешек. Можно еще попробовать сконфигурить 2х байтный ДМА трансфер, тк SPI регистр 2х байтный. Вероятно самый первый байт и портится, такая есть идея. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 11 мая, 2010 Опубликовано 11 мая, 2010 · Жалоба HOUSEHOUSE, а Вы обратили внимание на последнее предложение из описания работы DMA на прием из SPI? Очень похоже, что сдвиг у Вас получается именно оттуда. In Receive mode, as long as there is data in the SPI DMA FIFO (the FIFO is not empty), the SPI continues to request a DMA write to memory. The DMA engine continues to read a word from the SPI DMA FIFO and writes to memory until the SPI DMA Word Count register transitions from 1 to 0. The SPI continues receiving words until SPI DMA mode is disabled. ИМХО, ограниченность блекфиновского DMA в связке с SPI делает его малопригодным для протоколов сложнее 25xx флешки :( Конечно, сочетая работу поллингом и пересылки блоков можно работать и с SD, но принимать придется в обязательном порядке блок данных и CRC одновременно, что не всегда удобно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HOUSEHOUSE 0 11 мая, 2010 Опубликовано 11 мая, 2010 · Жалоба Вопрос для тех кто юзал BF542. Как там дело обстоит с аппаратной поддержкой SD? У меня приложение занимается либо сжатием видео потока либо аудио потока, потом это все мне нужно куда-то сохранить. Поэтому меня не устраивает ограниченность DMA и использование поллинга. Вопрос в том что смогу ли я на BF542 добится того что к примеру я послал через DMA 512 байт для записи на SD и забыл о них, потом в прерывании я просто проанализировал и возможно далее начал записывать. Т.е. мне нужно что бы процессор на носители тратил ограниченное время. С BF542 этого добиться можно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HOUSEHOUSE 0 13 мая, 2010 Опубликовано 13 мая, 2010 · Жалоба Прочитал даташит на BF542 и примеры стандартные в VisualDSP, предполагаю что там с SD вообще проблем не должно быть. У меня вопрос по поводу BF533 в общем я добился скорости 450-500 килобайт в секунду (я про SD). Но это не скорость записи на прямую в SD, а именно в файл, если писать без файловой системы то скорость чуточку быстрее. Запись я осуществляю с нулевого адресса (т.е. это первый банк SDRAM). Я подумал что такая низкая скорость может быть из-за медленного доступа к SDRAM и попытался подключить cache. Но после его подключение скорость практически не изменилась. У меня вопрос, все так и должно было быть? Или я кэш как-то не правильно подключаю? Я испробывал все виды кэшей, подключал как просто функции, так и создавал проект в котором все формируется напрямую перед main. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться