VHEMaster 0 28 августа, 2015 Опубликовано 28 августа, 2015 (изменено) · Жалоба Доброго времени суток! Проблема следующая Имеется контроллер 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 килобайта. Звук прерывается как раз во время чтения с флешки. Запись прикрепил. Думаю, оригинал все знают. Вот как выглядит дорожка Запись звука тут https://vk.com/maks_naumchuk?w=wall65222672_7202 Или тут http://rghost.ru/8MMx5y4Gt Помогите решить хотя-бы одну проблему Использую CooCox CoIDE и ARM-GCC компилятор. P.S. почему у меня не получилось ничего убрать под спойлер?.. Изменено 28 августа, 2015 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба Как объявлена AudioPoint? Если не volatile, то if имеет право на срабатывать. И есть ещё проблема. Дело в том, что с выключенной оптимизацией во время воспроизведения файла звук прерывается... С буфером на 128 семплов это вполне естественно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VHEMaster 0 28 августа, 2015 Опубликовано 28 августа, 2015 (изменено) · Жалоба Как объявлена AudioPoint? Если не volatile, то if имеет право на срабатывать. С буфером на 128 семплов это вполне естественно. Да, действительно. volatile помог с проблемой в оптимизации. Но проблема с прерывающимся звуком осталась. Но уже прерывается не так надолго. Сейчас сделаю запись с буфером 2048 байт. Вот запись http://rghost.ru/6CT76DDWJ Задержки уже не такие, но перерывы ещё заметны. Но всё-же хочется без них Изменено 28 августа, 2015 пользователем VHEMaster Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
miheyk 0 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба Но проблема с прерывающимся звуком осталась.В ARM чем больше число приоритета, тем ниже приоритет, выходит воспроизведение у вас выполняется в первую очередь, а уже потом USB-чтение. А если USB не может считать, то и играть нечего. Во-вторых, USB очень капризная вещь в плане таймингов, поэтому лучше ему поставить 0 и принять это отправной точкой для алгоритма программы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VHEMaster 0 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба В ARM чем больше число приоритета, тем ниже приоритет, выходит воспроизведение у вас выполняется в первую очередь, а уже потом USB-чтение. А если USB не может считать, то и играть нечего. Во-вторых, USB очень капризная вещь в плане таймингов, поэтому лучше ему поставить 0 и принять это отправной точкой для алгоритма программы. Проблема в том, что пока считывает данные с USB флешки, буфер постепенно опустошается, а когда кластер был считан то буфер снова заполняется. Т.е. программа организована так, что буфер может быть почти пуст только в начале и в конце воспроизведения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
miheyk 0 28 августа, 2015 Опубликовано 28 августа, 2015 (изменено) · Жалоба Для первой проблемы увеличьте буфер, чтобы он не переполнялся, но и не опустошался. Для второй проблемы постройте буферизацию, например, через кольцевой буфер. Это уже вопрос алгоритма. И не поленитесь прикрутить DMA к буферу. Изменено 28 августа, 2015 пользователем Mihey_K Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VHEMaster 0 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба Для первой проблемы увеличьте буфер, чтобы он не переполнялся, но и не опустошался. Для второй проблемы постройте буферизацию, например, через кольцевой буфер. Это уже вопрос алгоритма. И не поленитесь прикрутить DMA к буферу. Вопрос по поводу DMA. Как это организовать?) И ещё. Проблема была из-за багов в драйвере файловой системы. После их исправления всё стало быть отлично! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
king2 0 2 сентября, 2015 Опубликовано 2 сентября, 2015 · Жалоба Вопрос по поводу DMA. Как это организовать?) Есть у DMA отличный режим - называется circular, это когда DMA берет данные из буфера - доходит до конца буфера и начинает сначала. Один раз запустил - и само работает. Ну а Вам остается только ждать прерываний half transfer (запихать в первую половину буфера новые данные) и full transfer (то же самое, но вторая половина буфера). Таким образом, оно там само, а мы кормим ее пачками размером в половину буфера (я делаю это прямо из прерывания опять же по memory-to-memory DMA инициируя копирование следующей части данных). У меня запись, поэтому у меня есть огромный (мегабайт) буфер в SDRAM, и относительно маленький (16384) буфер для DMA. В прерываниях инициируем перетаскивание данных в большой буфер, по прерыванию mem-to-mem DMA обновляем указатель буфера, а уже из user task пишем на флешку (там могут быть залипания вплоть до полсекунды, если контроллер флешки именно сейчас решил чегонибудь внутри себя пооптимизировать). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться