Перейти к содержанию
    

в общем навешал на BF532 кодек VS1053

 

кратко соединения:

 

PF5 - XCS чипселект команд

PF6 - XDCS чипселект данных

PF7 - DREQ =0 когда занят

MOSI,MISO,SCK и чипселекты подтянуты к питанию через резистор 4.7kOm

 

грузится программа в L1 из eeprom - на PF2

 

программа ниже должна воспроизводить MIDI из массива MIDI[]

 

использую 8 битную передачу без ДМА, просто через SPI_TDBR

для начала пока хватит

 

не работает!!!

 

подскажите , верно ли с SPI работаю?

 

#include <cdefBF532.h>
#include <sysreg.h>

#define u8  unsigned char
#define u16 unsigned short int
#define u32 unsigned long int

#include "MIDI.c"

void Delay(u32 D)
{
while(--D);
}

void LED(u8 led)
{
*pFIO_FLAG_S=(led&1);
*pFIO_FLAG_C=((~led)&1);
ssync();
}

void Init_PLL(void)
{
*pSIC_IWR=0x00000001;
*pPLL_CTL=0x5000;     //VCO=CLKIN*40=400MHz, CLKIN=10MHz(Quartz)
*pPLL_DIV=0x0003;     //CCLK=VCO/1=400MHz, SCLK=VCO/3=133MHz
ssync();
*pVR_CTL=0x00DB;      //VLEV=1.2V, GAIN=20, FREQ=1MHz
ssync();
idle();
}

void Init_SDRAM(void)
{
while(!(*pEBIU_SDSTAT&1));
*pEBIU_SDSTAT|=0x10;
*pEBIU_SDRRC=0x0408;
*pEBIU_SDBCTL=0x0013;
*pEBIU_SDGCTL=0x0091998D;
*(u16*)0=0xBEEF;
while(*pEBIU_SDSTAT&8);
ssync();
}

void Init_FIO(void)
{
*pFIO_DIR=0x0001;  //PF0 на вывод, остальные на ввод
*pFIO_INEN=0x0080; //PF7 входной буфер разрешён, для остальных запрещён
ssync();
}

void Init_SPI(void)
{
*pSPI_CTL&=(~(1<<14));
*pSPI_FLG=(1<<14)|(1<<13)|(1<<10)|(1<<6)|(1<<5)|(1<<2);
*pSPI_BAUD=64;
*pSPI_CTL=0x3C01;
asm("ssync;");
*pSPI_CTL|=(1<<14);
asm("ssync;");
}

void XCS(u16 xcs) //XCS
{
*pSPI_FLG=(1<<14)|(xcs<<13)|(1<<10)|(1<<6)|(1<<5)|(1<<2);
asm("ssync;");
}

void XDCS(u16 xdcs) //XDCS
{
*pSPI_FLG=(xdcs<<14)|(1<<13)|(1<<10)|(1<<6)|(1<<5)|(1<<2);
asm("ssync;");
}

u8 DREQ(void) //DREQ
{
u8 dreq;
dreq=(*pFIO_FLAG_D>>7)&1;
asm("ssync;");
return dreq;
}

void OutVLSICommand(u8 Address,u16 Data) //Запись команды
{
XCS(0);
*pSPI_TDBR=0x02;
asm("ssync;");
while(!(*pSPI_STAT&1));
*pSPI_TDBR=Address;
asm("ssync;");
while(!(*pSPI_STAT&1));
*pSPI_TDBR=(Data>>8);
asm("ssync;");
while(!(*pSPI_STAT&1));
*pSPI_TDBR=(Data&0xFF);
asm("ssync;");
while(!(*pSPI_STAT&1));
XCS(1);
//while(!DREQ());
Delay(1000000);
}

void OutVLSIData(u8 Data) //Запись данных
{
XDCS(0);
*pSPI_TDBR=Data;
asm("ssync;");
while(!(*pSPI_STAT&1));
XDCS(1);
//while(!DREQ());
Delay(100000);
}

void Init_Codec(void)
{
OutVLSICommand(0x00,0x0804|(1<<7)|(1<<4));
Delay(1000000);
OutVLSICommand(0x00,0x0800|(1<<7)|(1<<4));
OutVLSICommand(0x02,0x0000);
OutVLSICommand(0x03,0x8800);
OutVLSICommand(0x05,44100|1);
OutVLSICommand(0x0B,0x0000);
}

void main(void)
{
static u32 midi=0;
Init_PLL();
Init_SDRAM();
Init_FIO();
Init_SPI();
LED(0);
Init_Codec();
LED(1);
while(1)
{
  OutVLSIData(MIDI[midi]);
  midi++;
  if(midi>=819) midi=0;
}
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

void XCS(u16 xcs) //XCS
{
*pSPI_FLG=(1<<14)|(xcs<<13)|(1<<10)|(1<<6)|(1<<5)|(1<<2);
asm("ssync;");
}

void XDCS(u16 xdcs) //XDCS
{
*pSPI_FLG=(xdcs<<14)|(1<<13)|(1<<10)|(1<<6)|(1<<5)|(1<<2);
asm("ssync;");
}

Не понятно что вы хотите сделать этими функциями. Если выбрать какой slave сейчас активен, то совершенно не верно. Устанавливая биты FLG вы выставляете состояние на портах(т.е. что записали то и будет на соответствующем пине). Также вы устанавливаете биты FLS2, FLS5, FLS6, т.е. на время передачи они у вас уходят в активное состояние одновременно. Если вы хотите именно выбирать текущее устройство, то надо сделать так

void XCS(u16 xcs) //XCS
{
*pSPI_FLG=(1<<14)|(xcs<<13)|(1<<10);
asm("ssync;");
}

void XDCS(u16 xdcs) //XDCS
{
*pSPI_FLG=(xdcs<<14)|(1<<13)|(1<<10);
asm("ssync;");
}

либо

void XCS(u16 xcs) //XCS
{
*pSPI_FLG=(1<<14)|(1<<13)|(1<<10)|(xcs<<5);
asm("ssync;");
}

void XDCS(u16 xdcs) //XDCS
{
*pSPI_FLG=(1<<14)|(1<<13)|(1<<10)|(xdcs<<6);
asm("ssync;");
}

 

Также установлен режим работы открытый коллектор бит WOM регистра SPI_CTL, а подтягивающий резистор есть на ноге MOSI.

 

Вот тут лежит корявый но всё таки перевод HW BF53x на русский язык.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

boom, переправил функции XCS и XDCS - всеравно не работает :(

 

и вообще мне логика флагов не понятна.

 

там же написано что биты FLG нужны для assert(spi cs=0) и deassert(spi cs=1), а FLS для того чтоб активизировать нужный cs

 

к примеру для PF5: SPI_FLG=(1<<5)|(cs<<13) где:

1<<5 - делаем активным PF5 для SPI CS#5

cs<<13 - =0/1 - assert/deassert SPI CS#5

 

по идее так.

в ваших же примерах (в первых) биты FLG=0, значит cоответствующий CS не заэнаблится.

 

исправьте, если я напутал...

 

--------

по ходу разбирательств выяснил, что кодеку нужен SPI MODE 0 - значит CPOL=0, CPHA=0

а это значит невозможно вручную дергать чипселект для регистра контроля (там надо передать 4 байта с опущеным CS)

 

получается, что чипселекты в моем случае нужно как программируемые флаги? И дергать их через FIO_FLAG_S,FIO_FLAG_D,FIO_FLAG_T

так?

 

 

 

тоесть надо организовать два типа передач по SPI:

 

для команд(32 бита): 0x02,Address,Data[15..8],Data[7..0]

XCS --------------|_______________________________|--------

 

и для данных: Data[7..0]

XDCS-----------|________|-------------

 

В кодеке по умолчанию биты передаются с MSB, заканчивая LSB

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

кстати, могут ли быть проблемы, если я не читаю регистр приема SPI?

 

и ещё : на miso/mosi/sck стоят подтягивающие резисторы на 4.7ком к питанию 3.3V

на xcs,xdcs резисторы на 100ком тоже по питанию

 

может ли в них дело быть?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

кстати, в переводе перепутаны значения некоторых битов в SPI-регистрах.

Берегитесь!!! :1111493779: :1111493779: :1111493779:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я дергаю CS только через флаги регистрами FIO_FLAG_S, FIO_FLAG_С.

Не могу понять что за конструкция SPI_FLG=(1<<5)|(cs<<13) при чем тут cs и 13 чему равен cs?

Лучше испльзуйте вот такие конструкции

*pSPI_CTL = SPE | MSTR | CPOL | CPHA | EMISO | 1;

*pFIO_DIR |= PF5|PF6|PF7;

*pFIO_FLAG_S = PF5; //set PF5

*pFIO_FLAG_C = PF5; // clear PF5

эти маски продефайнены в cdefBF531.h и их названия совпадают с приведенными в HW Reference.

Функция передачи/приема у меня выглядит вот так

char AT45ByteTransfer(char ch)
{
    char data;

    *pSPI_TDBR = ch;                // transmit data
    while(!(*pSPI_STAT & RXS));        // wait for received data, if RXS = 0 test it again

    data = *pSPI_RDBR;                // receive data
    return data;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не могу понять что за конструкция SPI_FLG=(1<<5)|(cs<<13) при чем тут cs и 13 чему равен cs?

 

это значит бит 5=1, активируем SPISEL5 (битовое поле FLS)

а cs<<13 - бит 13 - для assert/deassert SPICS5 (битовое поле FLG)

 

Лучше испльзуйте вот такие конструкции

*pSPI_CTL = SPE | MSTR | CPOL | CPHA | EMISO | 1;

*pFIO_DIR |= PF5|PF6|PF7;

*pFIO_FLAG_S = PF5; //set PF5

*pFIO_FLAG_C = PF5; // clear PF5

 

Поначалу нелегко использовать битовые поля. Мне пока проще в даташит залезть и посмотреть номера битов ;)

 

Функция передачи/приема у меня выглядит вот так

char AT45ByteTransfer(char ch)
{
    char data;

    *pSPI_TDBR = ch;                // transmit data
    while(!(*pSPI_STAT & RXS));        // wait for received data, if RXS = 0 test it again

    data = *pSPI_RDBR;                // receive data
    return data;
}

 

спасибо! попробую - результат напишу.

 

кстати, тот же кодек на арм9 работал со странностями - при передаче команд нужно было опрашивать регистр приёма SPI, а при передаче данных - можно было не опрашивать.

 

вот рабочее на арм9:

 

#define NPCS2 SPI_MR=0x00030011; //XCS
#define NPCS3 SPI_MR=0x00070011; //XDCS

#define VLSI_XCS(vlsi_xcs) \
{ \
A_ODSR=(A_ODSR&0xFFFFFFDF)|(vlsi_xcs<<5); \
PIOA_ODSR=A_ODSR; \
}

static void OutVLSICommand(u8 Address,u16 Data) //Запись команды
{
NPCS2
VLSI_XCS(0)
SPI_TDR=Address|0x0200;
while((SPI_SR&3)!=3);
SPI_RDR;
SPI_TDR=Data;
while((SPI_SR&3)!=3);
SPI_RDR;
VLSI_XCS(1)
while(!(PIOA_PDSR&0x00010000));
}

static void OutVLSIData(u8 Data) //Запись данных, чипселект тут аппаратно
{
NPCS3
SPI_TDR=Data;
while((SPI_SR&2)!=2);
}

//...

SPI_CSR2=0x00001A82; //XCS 16bit
SPI_CSR3=0x00000602; //XDCS 8bit
OutVLSICommand(0x00,0x0804);
Delay(1);
OutVLSICommand(0x02,0x0000);
OutVLSICommand(0x03,0x9000);
OutVLSICommand(0x05,44100|1);
OutVLSICommand(0x0B,0x0000);
for(i=0;i<44;i++)
{
  OutVLSIData(WAVHeader[i]);
  while(!DREQ());
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

кстати, в переводе перепутаны значения некоторых битов в SPI-регистрах.

Берегитесь!!! :1111493779: :1111493779: :1111493779:

А я и написал, что корявый. Там много где ошибки, но для понимания достаточно. Конкретные регистры и их биты смотреть лучше в оригинально описании.

 

...

Не могу понять что за конструкция SPI_FLG=(1<<5)|(cs<<13) при чем тут cs и 13 чему равен cs?

Лучше испльзуйте вот такие конструкции

*pSPI_CTL = SPE | MSTR | CPOL | CPHA | EMISO | 1;

*pFIO_DIR |= PF5|PF6|PF7;

*pFIO_FLAG_S = PF5; //set PF5

*pFIO_FLAG_C = PF5; // clear PF5

...

Согласен с uriy.

 

SPI очень гибко позволяет настроить свои параметры. Первоначально я тоже довольно долго разбирался с SPI BlackFin'а, ну а теперь он у меня трудностей никаких не вызывает. Можете кстати попробовать использовать драйвер порта SPI вместе с System Sevice и Device Manager.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

вот и я с вашей помощью пришел к выводу что чипселектами лучше рулить вручную через FIO.

так как вариант с SPI_FLG не перекрывает всех вариантов CPOL,CPHA когда нужно осуществлять передачи более 16 бит при CS=0

 

кстати просветите плиз, на счёт:

 

если у меня на mosi/miso/sck висят подтяжки на 4k7 на питание, будет ли лучше если я заактивирую режим Open Drain?

если широковещательный режим не не требуется, можно не устанавливать EMISO ?

Изменено пользователем denebopetukius

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

вот и я с вашей помощью пришел к выводу что чипселектами лучше рулить вручную через FIO.

так как вариант с SPI_FLG не перекрывает всех вариантов CPOL,CPHA когда нужно осуществлять передачи более 16 бит при CS=0

 

кстати просветите плиз, на счёт:

 

если у меня на mosi/miso/sck висят подтяжки на 4k7 на питание, будет ли лучше если я заактивирую режим Open Drain?

если широковещательный режим не не требуется, можно не устанавливать EMISO ?

 

 

В VDSP++ есть пример прямого программирования кодека SPI AD9866

Они используют для передачи функцию

 

void Send(unsigned short data)

{

*pSPI_TDBR = data;

asm("ssync;");

while (!(*pSPI_STAT & SPIF)); // wait until single-word transfer bit is set

while (!(*pSPI_STAT & RXS)); // wait until receive buffer full bit is set

 

stat = *pSPI_RDBR;

}

 

с ожиданием завершения и чтения и записи (в противном случае, если чтение не делать в регистре статуса будет выставлена ошибка чтения и если разрешено - даже произойдет прерывание по ошибке SPI)

 

Нужно аккуратно выставить совместимый с кодеком режим работы(CPOL, CHPA, TIMOD_) - и всё должно заработать

 

Аппаратный чипселект при CPHA=0 опускается автоматически при записи слова в регистр передачи, что

для многих устройств неприемлемо - он должен быть общий для всего блока обмена. А при программном управлении (СPHA=1) нет никакой разницы - управлять чипселектами как SPI_FLG или как флагами. Без разницы чем махать

 

SPI порт хоть и примитивный, но зато в отличие от SPORT он очень гибко программируется. Скорость и даже режимы

работы возможно менять прямо на лету и всё работает (многие устройства требуют смены полярности прямо на лету при переходе от записи к чтению, sampling edge и shifting edge меняются местами).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Обнаружил косяк с кодеком. по какой-то причине его нога DREQ после включения всей системы в низком лог. уровне- тоесть чип занят. выводится из этого состояния путём кратковременного закорачивания конденсатора цепочки сброса(100ком,0.1мкф) на землю.

после этого DREQ=1 и в моменты передачи кратковременно уходит в 0.

неужели еепром виноват?

 

 

Обнаружил косяк с кодеком. по какой-то причине его нога DREQ после включения всей системы в низком лог. уровне- тоесть чип занят. выводится из этого состояния путём кратковременного закорачивания конденсатора цепочки сброса(100ком,0.1мкф) на землю.

после этого DREQ=1 и в моменты передачи кратковременно уходит в 0.

неужели еепром виноват?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

как вы думаете, с чего начинать лечить эту проблему?

 

может конденсатор в цепи сброса взять больше?

или всё-таки дело в сильнотоковых подтяжках на 4k7? в схемах от vlsi ставят подтяжки на 100кОм(для кодека и сд-карты)

сможет ли блекфин нормально грузиться с еепром при подтяжках на miso/sck 100ком?, 43ком?

 

Вариант ресета с флага фина не предлагать - ибо сопли на плате не хочется :\

Изменено пользователем denebopetukius

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

может конденсатор в цепи сброса взять больше?

Эээ. Простите, а вы и для фина reset формируете с помощью RC-цепочки?

сможет ли блекфин нормально грузиться с еепром при подтяжках на miso/sck 100ком?, 43ком?

Не вижу препятствий.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для фина супервизор.

пробовал резисторы менять и кондёр сброса-не помогло!

нога кодека в нуле. иногда при подаче питания на плату-не уходит в нуль,но это редко.

что делать?

уже голову разбил!

у меня возле разъёма питания кондёр на 220мкф

или дело в фине который, возможно с spi 'неаккуратно' работает

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для фина супервизор.

пробовал резисторы менять и кондёр сброса-не помогло!

нога кодека в нуле. иногда при подаче питания на плату-не уходит в нуль,но это редко.

что делать?

уже голову разбил!

у меня возле разъёма питания кондёр на 220мкф

или дело в фине который, возможно с spi 'неаккуратно' работает

 

А фин и его spi здесь причём, если кодек не становится в начальное состояние по ресету?

 

В принципе, все SPI устройства (как и I2C) имеют такой недостаток, что после любой ошибки

конечный автомат порта устройства становится боком и больше без ресета не работает

У Вас он улетает незнамо куда уже при подаче питания

 

Нужно

1) при отладке иметь отдельный ресет, как минимум завести его с ресета процессора

или ещё с какой кнопки, хоть и проводом. Отлаживать серийную связь лучше всего

с помощью логического анализатора (осцилографа). Особенно если связь двухсторонняя, а прибор достаточно

сложный, чтобы охарактеризовать его состояние альтернативой работает-неработает (у меня у прибора больше 100 регистров и по поведению прибора очень трудно о чем-то судить, нужно видеть регистры)

2) после отладки ошибок уже не будет

 

У меня SPI фина отлично работает (в смысле комманд) с аналоговским DDC по шлейфу 15 см с частотой до 15 мгц

причем не только полингом, но и на прерываниях. На фин не надо гнать.

Там SPI хоть и с прибабахами (недокументироваными фичами), но вполне работающий

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...