Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32 - не работает код при включенной оптимизации
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
VHEMaster
Доброго времени суток! Проблема следующая
Имеется контроллер 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 */

}

CODE
Основная программа
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
И так далее

CODE
Вывод с 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 килобайта. Звук прерывается как раз во время чтения с флешки. Запись прикрепил. Думаю, оригинал все знают.
Вот как выглядит дорожка


Запись звука тут https://vk.com/maks_naumchuk?w=wall65222672_7202
Или тут http://rghost.ru/8MMx5y4Gt
Помогите решить хотя-бы одну проблему

Использую CooCox CoIDE и ARM-GCC компилятор.
P.S. почему у меня не получилось ничего убрать под спойлер?..
aaarrr
Как объявлена AudioPoint? Если не volatile, то if имеет право на срабатывать.

Цитата(VHEMaster @ Aug 28 2015, 16:09) *
И есть ещё проблема. Дело в том, что с выключенной оптимизацией во время воспроизведения файла звук прерывается...

С буфером на 128 семплов это вполне естественно.
VHEMaster
Цитата(aaarrr @ Aug 28 2015, 16:39) *
Как объявлена AudioPoint? Если не volatile, то if имеет право на срабатывать.


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

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

Вот запись http://rghost.ru/6CT76DDWJ
Задержки уже не такие, но перерывы ещё заметны. Но всё-же хочется без них
Mihey_K
Цитата
Но проблема с прерывающимся звуком осталась.
В ARM чем больше число приоритета, тем ниже приоритет, выходит воспроизведение у вас выполняется в первую очередь, а уже потом USB-чтение. А если USB не может считать, то и играть нечего. Во-вторых, USB очень капризная вещь в плане таймингов, поэтому лучше ему поставить 0 и принять это отправной точкой для алгоритма программы.
VHEMaster
Цитата(Mihey_K @ Aug 28 2015, 17:27) *
В ARM чем больше число приоритета, тем ниже приоритет, выходит воспроизведение у вас выполняется в первую очередь, а уже потом USB-чтение. А если USB не может считать, то и играть нечего. Во-вторых, USB очень капризная вещь в плане таймингов, поэтому лучше ему поставить 0 и принять это отправной точкой для алгоритма программы.

Проблема в том, что пока считывает данные с USB флешки, буфер постепенно опустошается, а когда кластер был считан то буфер снова заполняется. Т.е. программа организована так, что буфер может быть почти пуст только в начале и в конце воспроизведения.
Mihey_K
Для первой проблемы увеличьте буфер, чтобы он не переполнялся, но и не опустошался. Для второй проблемы постройте буферизацию, например, через кольцевой буфер. Это уже вопрос алгоритма. И не поленитесь прикрутить DMA к буферу.
VHEMaster
Цитата(Mihey_K @ Aug 28 2015, 18:50) *
Для первой проблемы увеличьте буфер, чтобы он не переполнялся, но и не опустошался. Для второй проблемы постройте буферизацию, например, через кольцевой буфер. Это уже вопрос алгоритма. И не поленитесь прикрутить DMA к буферу.

Вопрос по поводу DMA. Как это организовать?)
И ещё. Проблема была из-за багов в драйвере файловой системы. После их исправления всё стало быть отлично!
king2
Цитата(VHEMaster @ Aug 28 2015, 20:20) *
Вопрос по поводу DMA. Как это организовать?)

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

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