Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: SSC на AT91SAM7X256
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
mirr
Всем привет. у меня такая проблема: необходимо по SSC принимать данные от ПЛИС и отправлять их по Ethernet'y и это все на максимально возможной скорости. данные поступают порциями по 16 бит, передачу тактирует SSC.
сначала пакеты отправлял по udp, но не был уверен что все доходят, сейчас пока отправляю по TCP.
передача без ошибок, если SSC гоняет на 1МГц, если увеличить, то пропадают пакеты. MCLK = 86МГц.
знатоки, подскажите, можно ли ускорить весь этот процесс?
код:
CODE
void SSC_ReInit( void )
{
unsigned int SLOT_BY_FRAME = 1;
unsigned int BITS_BY_SLOT = 16;

pSSC->SSC_CR = AT91C_SSC_SWRST;

pSSC->SSC_CMR = 40;

*AT91C_SSC_TFMR = (AT91C_SSC_FSOS_POSITIVE |
(((SLOT_BY_FRAME-1)<<8) & AT91C_SSC_DATNB) |
AT91C_SSC_MSBF | (BITS_BY_SLOT-1));

*AT91C_SSC_RFMR = (AT91C_SSC_FSOS_POSITIVE |
(((SLOT_BY_FRAME-1)<<8) & AT91C_SSC_DATNB) | //AT91C_SSC_LOOP |
AT91C_SSC_MSBF | (BITS_BY_SLOT-1));

*AT91C_SSC_TCMR = (((((BITS_BY_SLOT*SLOT_BY_FRAME)/2) -1) <<24) |
AT91C_SSC_START_FALL_RF |
AT91C_SSC_CKO_CONTINOUS | AT91C_SSC_CKI | AT91C_SSC_CKS_DIV);
*AT91C_SSC_RCMR = (((((BITS_BY_SLOT*SLOT_BY_FRAME)/2) -1) <<24) |
AT91C_SSC_START_FALL_RF |
AT91C_SSC_CKO_CONTINOUS| AT91C_SSC_CKS_DIV);
}

-----------------------------------------------------------------
void BSP_SSC_Init( void )
{
// Init buffers

buffersRX[0] = &pBufferRX1[0];
buffersRX[1] = &pBufferRX2[0];
buffersRX[2] = &pBufferRX3[0];
buffersRX[3] = &pBufferRX4[0];

AT91F_SSC_CfgPIO();
AT91F_SSC_CfgPMC();

pSSC->SSC_IER = ( unsigned int )0x00;
pSSC->SSC_IDR = ( unsigned int )0xffff;

SSC_ReInit();

old_buff = 0;
next_buff = 1;

pSSC->SSC_RPR = (AT91_REG)buffersRX[0];
pSSC->SSC_RCR = SSCBUFSIZE;
pSSC->SSC_RNPR = (AT91_REG)buffersRX[1];
pSSC->SSC_RNCR = SSCBUFSIZE;

pAIC->AIC_IDCR = (1<<AT91C_ID_SSC);
pAIC->AIC_SVR[AT91C_ID_SSC] = (unsigned int)SscHandler;
pAIC->AIC_SMR[AT91C_ID_SSC] = (AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL|0x4);
pAIC->AIC_IECR = (1<<AT91C_ID_SSC);

pSSC->SSC_IER = /*AT91C_SSC_ENDTX|*/AT91C_SSC_ENDRX;
pSSC->SSC_IDR = ~(/*AT91C_SSC_ENDTX|*/AT91C_SSC_ENDRX);

pSSC->SSC_PTCR = /*AT91C_PDC_TXTEN|*/AT91C_PDC_RXTEN;
pSSC->SSC_CR = /*AT91C_SSC_TXEN|*/AT91C_SSC_RXEN;
}

-----------------------------------------------------------------

void SscHandler(void)
{
INT8U err;
INT8U flg;

unsigned long STATUS = AT91C_BASE_SSC->SSC_SR;

if ((STATUS & AT91C_SSC_ENDRX) == AT91C_SSC_ENDRX)
{
pSSC->SSC_IER = /*AT91C_SSC_ENDTX|*/AT91C_SSC_ENDRX;
OSQPost(CommQ, (void *)buffersRX[old_buff]);
old_buff = next_buff;

next_buff++;
if (next_buff == SSCBUFCOL) next_buff = 0;
pSSC->SSC_RNPR = (AT91_REG)buffersRX[next_buff];
pSSC->SSC_RNCR = SSCBUFSIZE;

}

if ((STATUS & AT91C_SSC_ENDTX) == AT91C_SSC_ENDTX)
{
pSSC->SSC_IER = AT91C_SSC_ENDTX;
pSSC->SSC_TNPR = (AT91_REG)pBufferTX1;
pSSC->SSC_TNCR = SSCBUFSIZE;
}

AT91C_BASE_AIC->AIC_IVR = 0;
AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_SSC);
}

------------------------------------------------

static void App_TaskUserIF (void *p_arg)
{
NET_SOCK_ID sock, sock_cl;
struct sockaddr_in client;
INT8U errMbox;
CPU_INT16U* pbuf;

// Init TCP/IP structures
client.sin_family = AF_INET;
client.sin_port = htons(11001);
client.sin_addr.s_addr = htonl(INADDR_ANY);

// Create socket
sock = socket(AF_INET, SOCK_STREAM, 0);
bind((int) sock,(struct sockaddr *)&client, (socklen_t)(sizeof (struct sockaddr_in)));

listen (sock,3);
sock_cl = accept (sock,(struct sockaddr *)&client, (socklen_t*)&errMbox);

// Init SSC
BSP_SSC_Init();

while(1)
{
pbuf = (CPU_INT16U*)OSQPend(CommQ, 0, &errMbox);
send(sock_cl,pbuf,2048,0);
};
}
aaarrr
Цитата(mirr @ Sep 10 2009, 17:02) *
передача без ошибок, если SSC гоняет на 1МГц, если увеличить, то пропадают пакеты. MCLK = 86МГц.

Во-первых, SSC работает нормально до MCLK/2. Во-вторых, MCLK = 86MHz - это очень-очень далеко за предельными 55MHz, поэтому может вообще ничего не работать.
mirr
ну а может быть так, что TCP просто не успевает отправить данные за то время пока SSC принимает новые?
может у меня как-то прием не правильно организован?
aaarrr
Цитата(mirr @ Sep 10 2009, 17:36) *
ну а может быть так, что TCP просто не успевает отправить данные за то время пока SSC принимает новые?

Ну так испытайте его производительность отдельно от SSC.

Цитата(mirr @ Sep 10 2009, 17:36) *
может у меня как-то прием не правильно организован?

На вид организован правильно, только SscHandler изобилует бессмысленными действиями:
Код
pSSC->SSC_IER = /*AT91C_SSC_ENDTX|*/AT91C_SSC_ENDRX;

pSSC->SSC_IER = AT91C_SSC_ENDTX;

AT91C_BASE_AIC->AIC_ICCR    =  (1 << AT91C_ID_SSC);

Вполне возможно, что где-то есть ошибки.
mirr
aaarrr, а Вам не приходилось разгонять SSC быстрее?
aaarrr
Цитата(mirr @ Sep 10 2009, 17:59) *
aaarrr, а Вам не приходилось разгонять SSC быстрее?

Ну, я не ставил себе целью специально его разгонять, но вполне нормально работает в одном из устройств на 4.096MHz в слейве и 1.4112MHz в мастере. Может, где-то делал и быстрее - не помню. В любом случае, он способен работать вплоть до MCLK/2.
mirr
Цитата(aaarrr @ Sep 10 2009, 17:17) *
Ну, я не ставил себе целью специально его разгонять, но вполне нормально работает в одном из устройств на 4.096MHz в слейве и 1.4112MHz в мастере. Может, где-то делал и быстрее - не помню. В любом случае, он способен работать вплоть до MCLK/2.

спасибо, буду бороться дальше...
AprilScan
На аналогичном контроллере использовал SSC с частотой 24 МГц (MCK/2) с DMA для получения данных от внешнего быстрого АЦП. В тестовом режиме работало без проблем. Привожу текст процедур без купюр, может будут полезны:

CODE
// External ADC (exADC) functions.
\*__________________________________________________________________________
______________*/
void exADC_init( void )
{
// Select A
exADC_port->PIO_ASR = exADC_SDATA_pin | exADC_SCLK_pin | exADC_CS_pin;
// Disable PIO
exADC_port->PIO_PDR = exADC_SDATA_pin | exADC_SCLK_pin | exADC_CS_pin;

//* Reset and Disable receiver and transmitter
pSSC->SSC_CR = AT91C_SSC_SWRST | AT91C_SSC_RXDIS | AT91C_SSC_TXDIS;
// Configuration of SSC Clock Mode Register
pSSC->SSC_CMR = 1; // DIV: Clock Divider (Clock equals MCK/(2*DIV))
// Configuration of SSC Receive Clock Mode Register
pSSC->SSC_RCMR = AT91C_SSC_CKS_DIV // Divided Clock
| AT91C_SSC_CKO_DATA_TX // Receive Clock only during data transfers
| AT91C_SSC_CKG_LOW // Receive Clock enabled only if RF Low
| AT91C_SSC_START_FALL_RF // Detection of a falling edge on RF signal
| ((unsigned int) 0x0A << 24); // Receive Period Divider Selection
// Configuration of SSC Receive Frame Mode Register
pSSC->SSC_RFMR = ((unsigned int) 0x0F) // (SSC) Data Length
| AT91C_SSC_MSBF // (SSC) Most Significant Bit First
| AT91C_SSC_FSOS_POSITIVE; // (SSC) Selected Receive Frame Sync Signal: Positive Pulse
}

void exADC_ReadString(void *pArray, uint16 szArray)
{
uint32 ulStart = millisecTimer(); // TEMP - for debug

Light_LED( LED2 ); // Light LED 2
TimeInterval = AT91C_BASE_RTTC->RTTC_RTVR; // Read RTT value
pSSC->SSC_CR = AT91C_SSC_RXEN; // Enable SSC receiver

// Receive data
pSSC->SSC_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS; // Disable transmitter and receiver
pSSC->SSC_RPR = (unsigned int) pArray; // address to the block to be received
pSSC->SSC_RCR = (unsigned int) szArray; // number of bytes to be received
pSSC->SSC_RNPR = 0; // address to the next block to be received
pSSC->SSC_RNCR = 0; // number of next bytes to be received
pSSC->SSC_PTCR = AT91C_PDC_RXTEN; // Enable PDC receiver

while (!(pSSC->SSC_SR & AT91C_SSC_RXBUFF))
{
if ( millisecTimer() - ulStart > 1000 ) break;
}
pSSC->SSC_CR = AT91C_SSC_RXDIS; // Disable SSC receiver
TimeInterval = AT91C_BASE_RTTC->RTTC_RTVR - TimeInterval;
Cancel_LED( LED2 );
CmndTime( 0, NULL );
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.