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

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. почему у меня не получилось ничего убрать под спойлер?..

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

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


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

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

 

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

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

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


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

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

 

 

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

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

 

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

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

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

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


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

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

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


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

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

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

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


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

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

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

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


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

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

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

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

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


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

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

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

 

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

 

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


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

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

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

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

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

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

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

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

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

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