Jump to content

    

stm32f407 SPI обнаружил косяк

При инициализации с делителем на 64 (с другими не проверял). SPI3 (с другими не проверял). stm407 на 168МГц (с другими не проверял).

После записи в регистр DR необходимо выждать задержку до проверки флага BSY в регистре SR. Иначе байт может потерятся (затерется следующим).

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

После установки задержки всё устаканилось.

Share this post


Link to post
Share on other sites
После записи в регистр DR необходимо выждать задержку до проверки флага BSY в регистре SR.

Имхо, не BSY нужно проверять, а TXE. А SPI на STM32 кажется и правда слегка шизанутый, обмен стартует с задержкой после записи в DR если в текущий момент еще ничего не передавалось. Есть у меня подозрение что это схема аппаратного руления CS не до конца отключена и паузы вставляет.

 

Share this post


Link to post
Share on other sites

Попробуйте проверять TXE, а не BSY. BSY это наверно когда непосредственно обмен начался.

post-19443-1353064062_thumb.jpg

Share this post


Link to post
Share on other sites

Я конечно понимаю, но

Bit 7 BSY: Busy flag

0: SPI (or I2S)not busy

1: SPI (or I2S)is busy in communication or Tx buffer is not empty

This flag is set and cleared by hardware.

И по моему у них в stdlib именно BSY используется ...

 

Share this post


Link to post
Share on other sites

наверное не просто так в RM написано

Note: Do not use the BSY flag to handle each data transmission or reception. It is better to use the

TXE and RXNE flags instead.

Share this post


Link to post
Share on other sites
При инициализации с делителем на 64 (с другими не проверял). SPI3 (с другими не проверял). stm407 на 168МГц (с другими не проверял).

Это есть во всех STM32... и ни какой это не косяк...

"Читать даташит до, а не после!"(С)

Note: 1 During discontinuous communications, there is a 2 APB clock period delay between the

write operation to SPI_DR and the BSY bit setting.

После записи в регистр DR необходимо выждать задержку до проверки флага BSY в регистре SR. Иначе байт может потерятся (затерется следующим).

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

После установки задержки всё устаканилось.

Если STM32F4 сидит на 168MHz, a APB SPI3 42MHz... сам и посчитай...

Всё правильно... никаких косяков и нет...

 

Edited by HHIMERA

Share this post


Link to post
Share on other sites
никаких косяков и нет...

C учётом последствий - это просто косяк описанный в даташите.

Там, кстати 2 APB. APB1 (SPI3) и APB2. APB1 по-моему у меня /2.

===

Спорить не буду - сложно посчитать будет. Да и не это главное... Написал, чтобы народ обратил внимание. Я не исключаю, что в другой периферии не может оказаться аналогичных проблем. Думаю из-за значительной скорости процессора.

Я не спорю, это можно описать как "особенности работы с узлами МК" ...

Так, у меня уже проявились "особенности" при работе с I2C и SPI. Так это только начало. Этот SPI работает с АЦП, а SPI1 будет с датафлэшем работать... Если там ещё особенности вылезут - опишу ... ))

Share this post


Link to post
Share on other sites
наверное не просто так в RM написано

Поддерживаю. Для полнодуплексного (даже если только передача нужна) SPI завершение передачи нужно проверять по... RXNE (и забыть о TXE или BSY, т.к. STM32F не поддерживает аппаратное формирование SS в режиме мастера!). Тогда будет абсолютная уверенность, что байт ушел, а следующий его не затрет по пути: ведь пока байт выдвигается по MOSI, входящий байт вдвигается по MISO тем же тактовым сигналом. Это означает, что флаг RXNE все равно возникнет, пусть позже TXE, зато наверняка после последнего такта. Нужно помнить чистить RXNE путем чтения DR перед записью туда:

 

1. Прочесть DR.

2. Записать в DR байт для передачи.

3. Ждать RXNE (будь-то тупо или путем реакции на прерывание).

4. Перейти к п.1., если еще есть данные для передачи.

Edited by KnightIgor

Share this post


Link to post
Share on other sites
Поддерживаю. Для полнодуплексного (даже если только передача нужна) SPI завершение передачи нужно проверять по... RXNE (и забыть о TXE или BSY, т.к. STM32F не поддерживает аппаратное формирование SS в режиме мастера!). Тогда будет абсолютная уверенность, что байт ушел, а следующий его не затрет по пути: ведь пока байт выдвигается по MOSI, входящий байт вдвигается по MISO тем же тактовым сигналом. Это означает, что флаг RXNE все равно возникнет, пусть позже TXE, зато наверняка после последнего такта. Нужно помнить чистить RXNE путем чтения DR перед записью туда:

Делал я так. Побочный эффект - обмен не непрерывный, между байтами пропуски получаются. При тактовой 15МГц, еле на 1МБайт/сек выходило. Пришлось сделать такой вариант:

IO_CALL_TYPE
DWORD
IO_CALL_OPTION
io_at45_read(void)
{
PSTM_SPI pspi = _AT_SPI_;
//
// В целях сохранения быстродействия не	производим проверку
// синхроресурса в функциях	самого нижнего уровня
//
//	IO_ASSERT( at45_mutex.holder ==	tn_curr_run_task, "AT45 synch failure");
//
for(;;)
{
	DWORD stat;
	//
	// Значительно более быстрый вариант - ждать TXE и немедленно
	// запускать новый цикл на SPI если буфер передатчика готов
	// Иначе контроллер делает паузы между символами. Чтобы не
	// потерять принимаемый символ при вытеснении потока, запуск
	// осуществляем при запрещенных прерываниях
	//
	stat = pspi->sSPI_SR;
	if (stat & bSPI_TXE)
	{
		DWORD lock, ret;

		lock = hal_lock_interrupt();
		pspi->sSPI_DR = 0xFF;

		for(;;)
		{
			//
			// Ждем завершения предыдущего цикла
			// и забираем принятые данные по готовности
			//
			if (stat & bSPI_RXNE) 
			{
				ret = pspi->sSPI_DR;
				break;
			}
			stat = pspi->sSPI_SR;
		}
		hal_unlock_interrupt(lock);
		return ret & 0xFF;			
	}
}
}

Скорость выросла раза в 1.5, DMA не пробовал - не очень подходт для задачи.

 

Share this post


Link to post
Share on other sites
Поддерживаю.

Да всё там просто...

Всё скрупулёзно и последовательно расписано в даташите...

Нужно просто воспринять TXE, RXNE и BSY так, как их задумал производитель... и обратить их во благо своё...

Вся эта чехарда с флагами, ИМХО, мнимая и надуманная...

Edited by HHIMERA

Share this post


Link to post
Share on other sites
Да всё там просто...

Ok. Не поленюсь и в понедельник проверю. Есть осциллограф - он чётко покажет. Какие вопросы.

Share this post


Link to post
Share on other sites
Это означает, что флаг RXNE все равно возникнет, пусть позже TXE, зато наверняка после последнего такта.

Кстати, не факт, что после. В зависимости от режима SPI, RXNE может возникать на середине последнего такта (если данные на приёме защёлкиваются по переднему фронту). Вот тут-то наверное и может пригодиться BSY. (Хотя я лично просто делаю несколько nop-ов перед отпусканием CS)

Share this post


Link to post
Share on other sites
Вот тут-то наверное и может пригодиться BSY.

Подтверждаю. CS по BSY работает корректно. И вообще. Минимальная библиотека получается. Единственное, что требуется задержка перед проверкой флага. Я на этом остановился. Меня это устраивает полностью. Правда пока я работаю с достаточно медленным АЦП. AD7192. Чуть позже, и по другому SPI буду работать с AT45DB... Пока не решил для себя как. Наверное, сначала, чтобы полностью проверить функционал прибора запущу его тем же драйвером. Потом, уже буду думать. Может ПДП буду испоьзовать и CRC аппаратный ... не знаю.

Share this post


Link to post
Share on other sites
1. Прочесть DR.

2. Записать в DR байт для передачи.

3. Ждать RXNE (будь-то тупо или путем реакции на прерывание).

4. Перейти к п.1., если еще есть данные для передачи.

Не получается: 1. Прочесть DR - после этого флаг RXNE не устанавливается (У меня разрешены прерывания по RXNE). Если сперва что-то записать в DR, то тогда RXNE устанавливается и происходит прерывание.

 

Еще вопрос как я понимаю при работе с SPI необходимо Мастером всегда толкать данные? Например data-flash at45db имеет команду для чтения manufacture id и device id длиной 1 байт=0x9FH, а ответ 6 байт, т.е. после подачи первого байта я должен еще подать 5 фиктивных байт?

Edited by sidy

Share this post


Link to post
Share on other sites
Не получается: 1. Прочесть DR - после этого флаг RXNE не устанавливается (У меня разрешены прерывания по RXNE). Если сперва что-то записать в DR, то тогда RXNE устанавливается и происходит прерывание.

 

Еще вопрос как я понимаю при работе с SPI необходимо Мастером всегда толкать данные? Например data-flash at45db имеет команду для чтения manufacture id и device id длиной 1 байт=0x9FH, а ответ 6 байт, т.е. после подачи первого байта я должен еще подать 5 фиктивных байт?

 

В любом случае микросхема SPI памяти не будет выталкивать из себя данные сама, для чтения нужно слать что-нибудь мастером, какие либо незначащие байты.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this