реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> STM32 сбои работы аппаратного CRC в SPI, непонятная работа аппаратного вычислителя CRC в модуле SPI
AlexUT4
сообщение Nov 23 2014, 14:15
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 2-05-11
Пользователь №: 64 731



Столкнулся с непонятками в работе аппаратного вычислителя CRC в модуле SPI у STM32F417.

Надо связать один мастер с многими слейвами через SPI (full duplex) с контрольной суммой. И всё это под управлением DMA. Написал мастер. В первом приближении работает сам на себе (loop back заделал). Но при проверках/отладках выяснилось, что, изредка, аппаратный вычислитель CRC на одной и той же последовательности битов НА ПЕРЕДАЧУ выдаёт РАЗНОЕ значение контрольной суммы. Это случается примерно 100 раз на 30000 верных значений. Частота появления ошибки не стабильна. Причём, неверные значения почти не повторяются. На приём всегда всё верно вычисляет. Флаг CRCERR срабатывает адекватно. На осциллографе наблюдается это чётко - на пине MOSI вижу статическую свою посылку (для теста взял 3 слова) за которой "подёргиваясь" идёт аппаратный CRC.
На сайте STMа народ тоже поднимал тему проблем работы аппаратного CRC в SPI - (ссылка). Что-то там решили, но их методы мне не помогли. Я пробовал все рекомендации из этого форума, но ни какова результата не дало (вообще ни каких изменений в частоте появления ошибки или в работе).
Пробовал менять степень полинома - не влияет. Влияет только само значение передаваемых слов: если все 0, то всё ОК; если все 1, то тоже все ОК; а если какие то другие рандумные значения, то начинаются сбои.

Сам алгоритм:

В задачи под работу SPI (использую FreeRFOT) в бесконечном цикле:
задержка
копирую что буду передавать в буфер SPI на передачу
выбираю нужный CS
инициализирую DMA
запускаю SPI
жду семафора
выключаю CS, DMA и SPI
смотрю и проверяю контрольные суммы
если все ОК - копирую принятые данные из приёмного буфера SPI в целевую переменную
CODE
static void vSPI_HI_Task( void *pvParameters )
{
channelsel = 0;

for(;; )
{
// делаем задержку перед запускоом следующего обмена
Delay1ms( SPI_HI_CHANNEL_SW_Delay );

// формируем пакет на передачу
memcpy((char *)&SPI_HI_TXbuf, SPI_HI_BUFFERS[channelsel].TXBUF, SPI_HI_BUFFERS[channelsel].TXBUF_SIZE);
SPI_HI_cur_ID = SPI_HI_TXbuf[0]; // запоминаем ID текущего модуля

// включаем нужный #EN
SPI_HI_EN( channelsel, RESET );

// перезапускаем DMA
SPI_HI_ReStart( MAX(SPI_HI_BUFFERS[channelsel].RXBUF_SIZE, SPI_HI_BUFFERS[channelsel].TXBUF_SIZE) );

// запустился цикл обмена по SPI HI

// Ждём семафора для разблокировки события - конец обмена по SPI HI
xSemaphoreTake( xSPI_HI_Semaphore, portMAX_DELAY );

// Обмен по SPI HI проведён

// выключаем нужный #EN
SPI_HI_EN( channelsel, SET );

// останавливаем DMA
DMA_Cmd(SPI_HI_TX_DMA_Stream, DISABLE);
while (DMA_GetCmdStatus(SPI_HI_TX_DMA_Stream)) {}
DMA_Cmd(SPI_HI_RX_DMA_Stream, DISABLE);
while (DMA_GetCmdStatus(SPI_HI_RX_DMA_Stream)) {}

//проверяем контрольную сумму
tx_crc[channelsel] = SPI_HI_SPI->TXCRCR;
rx_crc[channelsel] = SPI_HI_SPI->RXCRCR;
crc_b[channelsel] = crc_p;
if (SPI_I2S_GetFlagStatus(SPI_HI_SPI, SPI_FLAG_CRCERR))
{
// ошибка контрольной суммы
crc_e[channelsel] = crc_p;
SPI_HI_evtcnt.CRC_ERR[channelsel]++;
}
else
{
// контрольная сумма верна
// проверка что пришёл буфер от своего модуля
if ( SPI_HI_RXbuf[0] == SPI_HI_cur_ID )
{
// разбираем принятый буфер
memcpy(SPI_HI_BUFFERS[channelsel].RXBUF, (char *)&SPI_HI_RXbuf, SPI_HI_BUFFERS[channelsel].RXBUF_SIZE);
SPI_HI_evtcnt.EXCH_COMP[channelsel]++;
}
else
{
//пакет с неверным ID
SPI_HI_evtcnt.ID_ERR[channelsel]++;
SPI_HI_evtcnt.UNIT_STAT &= (uint32_t)~(((uint32_t)0x00000001) << channelsel);
}
}

// Disable SPI
SPI_I2S_ClearFlag(SPI_HI_SPI, SPI_FLAG_CRCERR); //Clears the SPI CRC Error
SPI_Cmd( SPI_HI_SPI, DISABLE );

// переходим на следующий канал
// channelsel++;
// if (channelsel >= SPI_HI_ChannelNumInWork) {channelsel = 0;}

}

}


В обработчике прерывания DMA конец приёма разрешаю прерывание SPI RXNE
CODE
//Global interupt for DMA SPI RX
void DMA_SPI_HI_RX_IRQHandler( void )
{
//NVIC_ClearPendingIRQ(SPI_HI_RX_DMA_IRQChannel); //сбрасываем запрос прерываниея NVIC

//Transfer complete
if (DMA_GetITStatus(SPI_HI_RX_DMA_Stream, DMA_IT_TCIF_SPIHI_RX))
{
DMA_ClearITPendingBit(SPI_HI_RX_DMA_Stream, DMA_IT_TCIF_SPIHI_RX);
SPI_HI_evtcnt.DMA_RX_TC++;
// конец пересылки основных данных
// разрешаем прерывание RXNE на приём последней посылки с контрольной суммой
SPI_I2S_ITConfig(SPI_HI_SPI, SPI_I2S_IT_RXNE, ENABLE);
}

//Transfer error
if (DMA_GetITStatus(SPI_HI_RX_DMA_Stream, DMA_IT_TEIF_SPIHI_RX))
{
DMA_ClearITPendingBit(SPI_HI_RX_DMA_Stream, DMA_IT_TEIF_SPIHI_RX);
SPI_HI_evtcnt.DMA_RX_TE++;
}

//Direct mode error
if (DMA_GetITStatus(SPI_HI_RX_DMA_Stream, DMA_IT_DMEIF_SPIHI_RX))
{
DMA_ClearITPendingBit(SPI_HI_RX_DMA_Stream, DMA_IT_DMEIF_SPIHI_RX);
SPI_HI_evtcnt.DMA_RX_DME++;
}

//FIFO overrun/underrun
if (DMA_GetITStatus(SPI_HI_RX_DMA_Stream, DMA_IT_FEIF_SPIHI_RX))
{
DMA_ClearITPendingBit(SPI_HI_RX_DMA_Stream, DMA_IT_FEIF_SPIHI_RX);
SPI_HI_evtcnt.DMA_RX_FE++;
}

}



В обработчике прерывания SPI RXNE делаю чтение приёмного регистра SPI, выключаю прерывание SPI RXNE, разблокирую семафор.
CODE
// Глобальный обработчик прерывания SPI
void SPI_HI_IRQHandler( void )
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
//NVIC_ClearPendingIRQ(SPI_HI_IRQChannel); //сбрасываем запрос прерывания NVIC

//RXNE
if (SPI_I2S_GetITStatus(SPI_HI_SPI, SPI_I2S_IT_RXNE))
{
// пришла последня посылка с контрольной суммой
SPI_I2S_ITConfig(SPI_HI_SPI, SPI_I2S_IT_RXNE, DISABLE); // отключаем это прерывание
crc_p = SPI_HI_SPI->DR; // пустое чтение для сброса флага прерывания
SPI_HI_evtcnt.RX_CRC++;

// разблокируем задачу vSPI_HI_Task через семафор
xSemaphoreGiveFromISR( xSPI_HI_Semaphore, &xHigherPriorityTaskWoken );
if( xHigherPriorityTaskWoken == pdTRUE )
{
taskYIELD();
}
}
}



CODE
// перезапуск SPI HI с заданием нужной длинны буфера buff
static void SPI_HI_ReStart( uint16_t buff )
{
buff = buff >> 1; // делим на 2 так как передаваемые данные 16-ти битные
DMA_SetCurrDataCounter(SPI_HI_TX_DMA_Stream, buff);
DMA_SetCurrDataCounter(SPI_HI_RX_DMA_Stream, buff);

DMA_ClearITPendingBit(SPI_HI_TX_DMA_Stream, DMA_IT_TCIF_SPIHI_TX);
DMA_ClearITPendingBit(SPI_HI_TX_DMA_Stream, DMA_IT_HTIF_SPIHI_TX);
DMA_ClearITPendingBit(SPI_HI_TX_DMA_Stream, DMA_IT_TEIF_SPIHI_TX);
DMA_ClearITPendingBit(SPI_HI_TX_DMA_Stream, DMA_IT_DMEIF_SPIHI_TX);
DMA_ClearITPendingBit(SPI_HI_TX_DMA_Stream, DMA_IT_FEIF_SPIHI_TX);

DMA_ClearITPendingBit(SPI_HI_RX_DMA_Stream, DMA_IT_TCIF_SPIHI_RX);
DMA_ClearITPendingBit(SPI_HI_RX_DMA_Stream, DMA_IT_HTIF_SPIHI_RX);
DMA_ClearITPendingBit(SPI_HI_RX_DMA_Stream, DMA_IT_TEIF_SPIHI_RX);
DMA_ClearITPendingBit(SPI_HI_RX_DMA_Stream, DMA_IT_DMEIF_SPIHI_RX);
DMA_ClearITPendingBit(SPI_HI_RX_DMA_Stream, DMA_IT_FEIF_SPIHI_RX);

DMA_Cmd(SPI_HI_TX_DMA_Stream, ENABLE);
while (!DMA_GetCmdStatus(SPI_HI_TX_DMA_Stream)) {}

DMA_Cmd(SPI_HI_RX_DMA_Stream, ENABLE);
while (!DMA_GetCmdStatus(SPI_HI_RX_DMA_Stream)) {}

SPI_CalculateCRC(SPI_HI_SPI, DISABLE); // Disable CRC
SPI_CalculateCRC(SPI_HI_SPI, ENABLE); // Enable CRC - clear CRC regs
SPI_I2S_ClearFlag(SPI_HI_SPI, SPI_FLAG_CRCERR); //Clears the SPI CRC Error
SPI_Cmd(SPI_HI_SPI, ENABLE); // Enable SPI
}


В чём может быть глюк?

Сообщение отредактировал IgorKossak - Nov 23 2014, 19:53
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!


--------------------
Александр, UT4UBL
Go to the top of the page
 
+Quote Post
AlexUT4
сообщение Nov 23 2014, 20:23
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 2-05-11
Пользователь №: 64 731



Код инициализации:

CODE

// инициализация SPI
// APB1 CLK = 168/4 = 42 MHz
// APB2 CLK = 168/2 = 84 MHz
// включаем тактирование модуля SPI
if ( (SPI_HI_CLK == RCC_APB1Periph_SPI2) || (SPI_HI_CLK == RCC_APB1Periph_SPI3) )
{ RCC_APB1PeriphClockCmd(SPI_HI_CLK, ENABLE); }
else { RCC_APB2PeriphClockCmd(SPI_HI_CLK, ENABLE); }

SPI_StructInit(&SPI_InitStructure);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; //
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 16;
SPI_Init(SPI_HI_SPI, &SPI_InitStructure);

SPI_CalculateCRC(SPI_HI_SPI, ENABLE); //Enable CRC

SPI_SSOutputCmd(SPI_HI_SPI, DISABLE); // Disable the selected SPI SS output
SPI_NSSInternalSoftwareConfig(SPI_HI_SPI, SPI_NSSInternalSoft_Set); // Set NSS pin internally by software

SPI_I2S_ITConfig(SPI_HI_SPI, SPI_I2S_IT_TXE, DISABLE); // interrupts
SPI_I2S_ITConfig(SPI_HI_SPI, SPI_I2S_IT_RXNE, DISABLE);
SPI_I2S_ITConfig(SPI_HI_SPI, SPI_I2S_IT_ERR, DISABLE);

SPI_I2S_DMACmd(SPI_HI_SPI, SPI_I2S_DMAReq_Tx, ENABLE); // Enables DMA TX request
SPI_I2S_DMACmd(SPI_HI_SPI, SPI_I2S_DMAReq_Rx, ENABLE); // Enables DMA RX request

// включаем прерывание блока NVIC для SPI
NVIC_InitStructure.NVIC_IRQChannel = SPI_HI_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = SPI_HI_IRQChannel_Prio;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_ClearPendingIRQ(SPI_HI_IRQChannel);

// настраиваем DMA
// включение тактовой частоты для блока DMA
RCC_AHB1PeriphClockCmd(SPI_HI_DMA_CLK, ENABLE);
// Disable DMA channel SPI
DMA_Cmd(SPI_HI_TX_DMA_Stream, DISABLE);
DMA_Cmd(SPI_HI_RX_DMA_Stream, DISABLE);

// DMA channel SPI HI TX configuration
DMA_DeInit(SPI_HI_TX_DMA_Stream);
DMA_InitStructure.DMA_Channel = SPI_HI_TX_DMA_Channel;
DMA_InitStructure.DMA_PeripheralBaseAddr = SPI_HI_DR_Address;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI_HI_TXbuf;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = MAX(SPI_HI_BUFFERS[0].RXBUF_SIZE, SPI_HI_BUFFERS[0].TXBUF_SIZE);
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(SPI_HI_TX_DMA_Stream, &DMA_InitStructure);

// включаем прерывание блока NVIC для DMA TX
NVIC_InitStructure.NVIC_IRQChannel = SPI_HI_TX_DMA_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = SPI_HI_TX_DMA_IRQChannel_Prio;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_ClearPendingIRQ(SPI_HI_TX_DMA_IRQChannel);

DMA_ClearITPendingBit(SPI_HI_TX_DMA_Stream, DMA_IT_TCIF_SPIHI_TX);
DMA_ClearITPendingBit(SPI_HI_TX_DMA_Stream, DMA_IT_HTIF_SPIHI_TX);
DMA_ClearITPendingBit(SPI_HI_TX_DMA_Stream, DMA_IT_TEIF_SPIHI_TX);
DMA_ClearITPendingBit(SPI_HI_TX_DMA_Stream, DMA_IT_DMEIF_SPIHI_TX);
DMA_ClearITPendingBit(SPI_HI_TX_DMA_Stream, DMA_IT_FEIF_SPIHI_TX);

DMA_ITConfig(SPI_HI_TX_DMA_Stream, DMA_IT_TC, ENABLE);
DMA_ITConfig(SPI_HI_TX_DMA_Stream, DMA_IT_HT, DISABLE);
DMA_ITConfig(SPI_HI_TX_DMA_Stream, DMA_IT_TE, ENABLE);
DMA_ITConfig(SPI_HI_TX_DMA_Stream, DMA_IT_DME, ENABLE);
DMA_ITConfig(SPI_HI_TX_DMA_Stream, DMA_IT_FE, ENABLE);

// DMA channel SPI LO RX configuration
DMA_DeInit(SPI_HI_RX_DMA_Stream);
DMA_InitStructure.DMA_Channel = SPI_HI_RX_DMA_Channel;
DMA_InitStructure.DMA_PeripheralBaseAddr = SPI_HI_DR_Address;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI_HI_RXbuf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = MAX(SPI_HI_BUFFERS[0].RXBUF_SIZE, SPI_HI_BUFFERS[0].TXBUF_SIZE);
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(SPI_HI_RX_DMA_Stream, &DMA_InitStructure);

// включаем прерывание блока NVIC для DMA RX
NVIC_InitStructure.NVIC_IRQChannel = SPI_HI_RX_DMA_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = SPI_HI_RX_DMA_IRQChannel_Prio;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_ClearPendingIRQ(SPI_HI_RX_DMA_IRQChannel);

DMA_ClearITPendingBit(SPI_HI_RX_DMA_Stream, DMA_IT_TCIF_SPIHI_RX);
DMA_ClearITPendingBit(SPI_HI_RX_DMA_Stream, DMA_IT_HTIF_SPIHI_RX);
DMA_ClearITPendingBit(SPI_HI_RX_DMA_Stream, DMA_IT_TEIF_SPIHI_RX);
DMA_ClearITPendingBit(SPI_HI_RX_DMA_Stream, DMA_IT_DMEIF_SPIHI_RX);
DMA_ClearITPendingBit(SPI_HI_RX_DMA_Stream, DMA_IT_FEIF_SPIHI_RX);

DMA_ITConfig(SPI_HI_RX_DMA_Stream, DMA_IT_TC, ENABLE);
DMA_ITConfig(SPI_HI_RX_DMA_Stream, DMA_IT_HT, DISABLE);
DMA_ITConfig(SPI_HI_RX_DMA_Stream, DMA_IT_TE, ENABLE);
DMA_ITConfig(SPI_HI_RX_DMA_Stream, DMA_IT_DME, ENABLE);
DMA_ITConfig(SPI_HI_RX_DMA_Stream, DMA_IT_FE, ENABLE);


--------------------
Александр, UT4UBL
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Nov 24 2014, 06:36
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Я уже где-то писал. Экспериментировал с stm32f407. CRC, реально применить не получилось. Механизм включения выключения не работает. (Там автоматически CRC инитится) и ещё куча всего. Я уже сейчас слабо помню. В мануале об этом и многом другом упоминается. Никаким внятным способом заставить работать не получилось. Результаты были непредсказуемы. Для каких целей они его разработали и как работает - непонятно. Я хотел применить для работы с флэш памятью. Типа просчитывать при записи блока.
Go to the top of the page
 
+Quote Post
AlexUT4
сообщение Nov 24 2014, 07:12
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 2-05-11
Пользователь №: 64 731



Цитата(SasaVitebsk @ Nov 24 2014, 09:36) *
Я уже где-то писал. Экспериментировал с stm32f407. CRC, реально применить не получилось. Механизм включения выключения не работает. (Там автоматически CRC инитится) и ещё куча всего. Я уже сейчас слабо помню. В мануале об этом и многом другом упоминается. Никаким внятным способом заставить работать не получилось. Результаты были непредсказуемы. Для каких целей они его разработали и как работает - непонятно. Я хотел применить для работы с флэш памятью. Типа просчитывать при записи блока.



Спасибо за ответ. Теперь немного проясняется. Искал по нету и по этому форуму, но не нашёл подобной проблемы. На форуме ST вроде решили проблему, но у них другой МК был. сегодня еще поэксперементирую.


--------------------
Александр, UT4UBL
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Nov 25 2014, 13:11
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Плохо искали ... ))
http://electronix.ru/forum/index.php?showt...%EA%EE%F1%FF%EA
Go to the top of the page
 
+Quote Post
ViKo
сообщение Nov 25 2014, 13:22
Сообщение #6


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Ничего не понял ни здесь, ни в указанной выше ветке. Какие проблемы? У меня так работает в STM32F207:
Код
void Ctrl_calc(void)
{
  CRC->CR = CRC_CR_RESET;
  uint32_t *data = (uint32_t *) &Ctrl;
  uint32_t size = sizeof(Ctrl_t) / 4 - 1;
  for (; size--; ) {
    CRC->DR = *data++;
  }
  *data = CRC->DR;        // сохранить CRC в конец структуры
}

В другой функции проверяется CRC (вычисляется для той же структуры, включая и саму CRC, и если она равна 0, то считаю, что содержимое структуры верное. Работает.

Ой! Здесь же про CRC в SPI говорится. С ней не работал.
Go to the top of the page
 
+Quote Post
AlexUT4
сообщение Nov 25 2014, 14:38
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 2-05-11
Пользователь №: 64 731



Цитата(SasaVitebsk @ Nov 25 2014, 16:11) *


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

Перепробовал все возможности и даже на разных контроллерах - ничего не помогает. Только немного меняет частоту ошибок если работать с другой областью памяти, но это не панацея.

Буду делать программный подсчёт.


--------------------
Александр, UT4UBL
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Nov 26 2014, 08:21
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(AlexUT4 @ Nov 25 2014, 17:38) *
Вы в основном о трудностях применения в конкретной вашей задаче....

И да и нет.
SPI это только интерфейс. Абсолютно выхолощенный. Соответственно работа с ним требует протокола. Проще говоря, ну и посчитали вы CRC, её же куда-то вставить нужно. То есть транспортного уровня недостаточно, требуются пакеты, команды и так далее .. Таким образом, работа с датафлэш, это абсолютно типовая задача.
Применительно к пакетам требуется инициализировать CRC, и включать выключать подсчёт. Очевидно, что у st с этим возникли трудности, и причины этого скорее всего в синхронизации. Скорее всего подсчёт CRC идёт при передаче (так проще), а передача относительно асинхронна.
Поэтому, на мой взгляд, они либо должны были указать для какой конкретно цели (устройства) они разрабатывали данную фичу, либо должны были показать примеры работы с тем либо иным устройством, ну или хотя бы абстрактный пример привести. Ну чтобы я или Вы сразу бы определили подходит данный узел под вашу задачу или нет, а не тратили кучу времени на исследования в области ...
Go to the top of the page
 
+Quote Post
AlexUT4
сообщение Nov 26 2014, 14:46
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 2-05-11
Пользователь №: 64 731



Цитата(SasaVitebsk @ Nov 26 2014, 11:21) *
И да и нет.
SPI это только интерфейс. Абсолютно выхолощенный. Соответственно работа с ним требует протокола. Проще говоря, ну и посчитали вы CRC, её же куда-то вставить нужно. То есть транспортного уровня недостаточно, требуются пакеты, команды и так далее .. Таким образом, работа с датафлэш, это абсолютно типовая задача.
Применительно к пакетам требуется инициализировать CRC, и включать выключать подсчёт. Очевидно, что у st с этим возникли трудности, и причины этого скорее всего в синхронизации. Скорее всего подсчёт CRC идёт при передаче (так проще), а передача относительно асинхронна.
Поэтому, на мой взгляд, они либо должны были указать для какой конкретно цели (устройства) они разрабатывали данную фичу, либо должны были показать примеры работы с тем либо иным устройством, ну или хотя бы абстрактный пример привести. Ну чтобы я или Вы сразу бы определили подходит данный узел под вашу задачу или нет, а не тратили кучу времени на исследования в области ...


Они разработали очень нужную фичу этот аппаратный CRC. В основном он применяется для связи двух МК или другой "умной" периферии с относительно простым, пользовательским протоколом верхнего уровня (как у меня, например) где подсчёт CRC делается на весь пакет. Для всяких микросхем памяти, где CRC используется не на канальном уровне этот модуль применять бессмысленно.
Примеров я видел множество, но не ST-шных. Мне кажется, что они знают, что начудили с этим модулем, и очень скромно его описывают и обходят в примерах.
Ну и ещё раз повторюсь: модуль чётко работает по даташиту, НО глючит (не стабилен) только на передачу.
Сейчас заделал программный подсчёт CRC - полёт нормальный)))


--------------------
Александр, UT4UBL
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Nov 26 2014, 16:00
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Как он может в одну сторону глючить а в другую нет?
Как проверялось что на прием не ошибается? Так может для передачи сначала делать типа псевдоприем с ДМА, получать цифру суммы а потом все выдавливать наружу с правильным кодом?
Go to the top of the page
 
+Quote Post
AlexUT4
сообщение Nov 26 2014, 16:43
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 2-05-11
Пользователь №: 64 731



Цитата(Golikov A. @ Nov 26 2014, 19:00) *
Как он может в одну сторону глючить а в другую нет?

Это вопросы к ST. Там два независимых аппаратных блока расчёта CRC: одни на приём, другой на передачу.


Цитата(Golikov A. @ Nov 26 2014, 19:00) *
Как проверялось что на прием не ошибается? Так может для передачи сначала делать типа псевдоприем с ДМА, получать цифру суммы а потом все выдавливать наружу с правильным кодом?


Использую счётчики исключений/событий. За всё время наблюдений (неделю целую убил на это) на приём всегда было ОК. Посмотрите как он работает что на приём что на передачу. Я ему даю пакет и запускаю, а дальше он сам аппаратно всё делает без моего участия: DMA даёт блоку SPI байт/слово, SPI, в свою очередь передаёт его из микросхемы и попутно "на лету" побитно рассчитывает контрольную сумму и в конце передачи САМ передаёт эту контрольную сумму. На выходе я реально наблюдаю на осциллографе статический пакет и "дёргающуюся" контрольную сумму.

Предполагаю глюки самого проца. Пока нет времени писать с STшный сапот.


--------------------
Александр, UT4UBL
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Nov 26 2014, 17:03
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



а на приеме он может ОК говорить и на не неправильные - не сошедшиеся суммы, может он так ошибается, так что то что не было ерроров не факт что оно работаетsm.gif
Go to the top of the page
 
+Quote Post
AlexUT4
сообщение Nov 26 2014, 18:59
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 2-05-11
Пользователь №: 64 731



Цитата(Golikov A. @ Nov 26 2014, 20:03) *
а на приеме он может ОК говорить и на не неправильные - не сошедшиеся суммы, может он так ошибается, так что то что не было ерроров не факт что оно работаетsm.gif


я заводил счётчик и на такое событие - не замечал расхождений на приём.


--------------------
Александр, UT4UBL
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Nov 27 2014, 05:59
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



В общем-то что такое CRC? Это сдвиг и исключающее ИЛИ. В данном случае, когда идёт битовый поток, то подсчёт битов и исключающее ИЛИ. То есть схемотехнически это с десяток вентилей, не больше. Причём статических. Как-то не вяжется, что они могут сбоить. Не верю.
Там нахомучено что-то именно с инициализацией и запретом - это точно.
Может какие-то вопросы по DMA? Сейчас гляну.
PS: Почитал. Они в этой части существенно изменили мануал. Появилась последовательность инициализации и действий. Когда я писал - этого не было. Там написано, что в DMA режиме не требуется NEXT передавать, а я думал в ручную, после завершения DMA транзакции. Тогда непонятно. Здесь даже и ошибиться сложно. По сути инициализируешь SPI формируешь буфер и в DMA указываешь адрес и размер. Всё должно в автомате работать.

Может скорость слишком большая? Там не выше 42МГц, на сколько я помню.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Nov 27 2014, 10:47
Сообщение #15


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Общее соображение: когда в STM-ке что-то работает нестабильно, надо добавить барьерчиков.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 14:29
Рейтинг@Mail.ru


Страница сгенерированна за 0.10549 секунд с 7
ELECTRONIX ©2004-2016