Jump to content

    

STM32 - не работает код при включенной оптимизации

Доброго времени суток! Проблема следующая

Имеется контроллер STM32F407ZET6. Вместе с ним на плате USB флешка, UART и ЦАП.

При выключенной оптимизации код работает без проблем.

Обработчик прерываний
void TIM6_DAC_IRQHandler(void)
{
  /* USER CODE BEGIN TIM6_DAC_IRQn 0 */

  /* USER CODE END TIM6_DAC_IRQn 0 */
  HAL_DAC_IRQHandler(&hdac);
  HAL_TIM_IRQHandler(&htim6);//Сброс флагов
  /* USER CODE BEGIN TIM6_DAC_IRQn 1 */


  HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_L, L_Buffer[AudioPoint]);//Выводим в ЦАП
  HAL_DAC_SetValue(&hdac, DAC_CHANNEL_2, DAC_ALIGN_12B_L, R_Buffer[AudioPoint]);
  print("D %d %d\n\r",2,i,AudioPoint);//Дебаг. 
  AudioPoint++;//Освобождаем ячейку
  if(AudioPoint >= BUFFERSIZE) AudioPoint = 0;
  /* USER CODE END TIM6_DAC_IRQn 1 */

}

Основная программа
		BUFFERSIZE = 128; //Количество сэмплов в буффере
		AudioPoint = BUFFERSIZE;
		uint8_t Bytes = FileBuff[32];//Байт на сэмпл WAVE
		length = BUFFERSIZE*Bytes;//Длинна блока
		uint8_t ftime = 1;//В первый раз(антибаг)
		while(f_eof(&File))//Пока файл не кончился
		{
			if(File.Size-File.CurrentByte < length) length = File.Size-File.CurrentByte;//Антибаг
			if(f_read(&File, FileBuff, length)) { print("File read error!",0); goto error; }//Чтение

			print("R\n\r",0);//Дебаг
			i = 0;//Обнуляем указатель
			while(i<BUFFERSIZE)//Пока буффер из носителя не будет полностью считан
			{
//////////////////////////////////////////////////////////////////////////////
				if(i != AudioPoint)//Вот тут вот какая-то херня. Если ячейка буффера ЦАПа освободилась, записываем в неё новое значение
				{
					L_Buffer[i]  = FileBuff[(i*Bytes)+1]<<8;//Заполняем ячейку буффера "звук"
					L_Buffer[i] += FileBuff[(i*Bytes)];
					L_Buffer[i] ^= 0x8000;
					R_Buffer[i]  = FileBuff[(i*Bytes)+3]<<8;
					R_Buffer[i] += FileBuff[(i*Bytes)+2];
					R_Buffer[i] ^= 0x8000;
					print("F %d %d\n\r",2,i,AudioPoint);//Дебаг
					i += 1;//Добавляем единичку
				}
//////////////////////////////////////////////////////////////////////////////
			}
			if(ftime) { AudioPoint = 0; HAL_TIM_Base_Start_IT(&htim6); ftime = 0; }//В первый проход запускаем таймер

		}
		ftime = 1;
		HAL_TIM_Base_Stop_IT(&htim6);//Файл закончился, останавливаем таймер
		print("Done! Thanks!\n\r", 0);//Благодарность
		error:
		while(1);//Программа закончена

Происходит чтение WAV файла в свободные ячейки буффера. Проблема в том, что в основном коде (где выделено) не срабатывает "if" с включенной оптимизацией.

Вывод с UART при включенной оптимизацией. Не работает!
Opening "A:\EnterSandman.wav"
R
F 0 128
F 1 128
F 2 128
Заполнение буффера
F 126 128
F 127 128
D 128 0
R
F 0 1
D 1 1
D 1 2
D 1 3
И так далее

Вывод с UART при отключенной оптимизации. Работает!
Opening "A:\EnterSandman.wav"
R
F 0 128
F 1 128
F 2 128
F 3 128
F 4 128
F 5 128
F 6 128
Заполнение буффера
F 124 128
F 125 128
F 126 128
F 127 128
D 128 0
R
F 0 1
D 1 1
F 1 2
D 2 2
F 2 3
D 3 3
F 3 4
D 4 4
F 4 5
D 5 5
F 5 6
D 6 6
F 6 7
D 7 7
И так далее

!Скорость ЦАПа была занижена до 5 Гц чтобы данные для отладки не искажались.

И есть ещё проблема. Дело в том, что с выключенной оптимизацией во время воспроизведения файла звук прерывается... Приоритет у TIM6 стоит 0, у USB флешки, с которой происходит чтение, вообще 5. Использую библиотеку HAL для обслуживания флешки. Чтение идёт по одному кластеру размером в 32 килобайта. Звук прерывается как раз во время чтения с флешки. Запись прикрепил. Думаю, оригинал все знают.

Вот как выглядит дорожка

qpb4ki877.png

qpb4qmajb.png

Запись звука тут https://vk.com/maks_naumchuk?w=wall65222672_7202

Или тут http://rghost.ru/8MMx5y4Gt

Помогите решить хотя-бы одну проблему

 

Использую CooCox CoIDE и ARM-GCC компилятор.

P.S. почему у меня не получилось ничего убрать под спойлер?..

Edited by IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Share this post


Link to post
Share on other sites

Как объявлена AudioPoint? Если не volatile, то if имеет право на срабатывать.

 

И есть ещё проблема. Дело в том, что с выключенной оптимизацией во время воспроизведения файла звук прерывается...

С буфером на 128 семплов это вполне естественно.

Share this post


Link to post
Share on other sites
Как объявлена AudioPoint? Если не volatile, то if имеет право на срабатывать.

 

 

С буфером на 128 семплов это вполне естественно.

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

 

Вот запись http://rghost.ru/6CT76DDWJ

Задержки уже не такие, но перерывы ещё заметны. Но всё-же хочется без них

Edited by VHEMaster

Share this post


Link to post
Share on other sites
Но проблема с прерывающимся звуком осталась.
В ARM чем больше число приоритета, тем ниже приоритет, выходит воспроизведение у вас выполняется в первую очередь, а уже потом USB-чтение. А если USB не может считать, то и играть нечего. Во-вторых, USB очень капризная вещь в плане таймингов, поэтому лучше ему поставить 0 и принять это отправной точкой для алгоритма программы.

Share this post


Link to post
Share on other sites
В ARM чем больше число приоритета, тем ниже приоритет, выходит воспроизведение у вас выполняется в первую очередь, а уже потом USB-чтение. А если USB не может считать, то и играть нечего. Во-вторых, USB очень капризная вещь в плане таймингов, поэтому лучше ему поставить 0 и принять это отправной точкой для алгоритма программы.

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

Share this post


Link to post
Share on other sites

Для первой проблемы увеличьте буфер, чтобы он не переполнялся, но и не опустошался. Для второй проблемы постройте буферизацию, например, через кольцевой буфер. Это уже вопрос алгоритма. И не поленитесь прикрутить DMA к буферу.

Edited by Mihey_K

Share this post


Link to post
Share on other sites
Для первой проблемы увеличьте буфер, чтобы он не переполнялся, но и не опустошался. Для второй проблемы постройте буферизацию, например, через кольцевой буфер. Это уже вопрос алгоритма. И не поленитесь прикрутить DMA к буферу.

Вопрос по поводу DMA. Как это организовать?)

И ещё. Проблема была из-за багов в драйвере файловой системы. После их исправления всё стало быть отлично!

Share this post


Link to post
Share on other sites
Вопрос по поводу DMA. Как это организовать?)

Есть у DMA отличный режим - называется circular, это когда DMA берет данные из буфера - доходит до конца буфера и начинает сначала. Один раз запустил - и само работает. Ну а Вам остается только ждать прерываний half transfer (запихать в первую половину буфера новые данные) и full transfer (то же самое, но вторая половина буфера).

 

Таким образом, оно там само, а мы кормим ее пачками размером в половину буфера (я делаю это прямо из прерывания опять же по memory-to-memory DMA инициируя копирование следующей части данных). У меня запись, поэтому у меня есть огромный (мегабайт) буфер в SDRAM, и относительно маленький (16384) буфер для DMA. В прерываниях инициируем перетаскивание данных в большой буфер, по прерыванию mem-to-mem DMA обновляем указатель буфера, а уже из user task пишем на флешку (там могут быть залипания вплоть до полсекунды, если контроллер флешки именно сейчас решил чегонибудь внутри себя пооптимизировать).

 

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