jcxz 241 3 декабря, 2015 Опубликовано 3 декабря, 2015 · Жалоба С трудом это представляю. При настройке DMA надо указать адреса в кольцевом буфере. Для 4-х DMA то есть будет 4 адреса со смещением на длину пакета. А если вдруг не придут данные от одной из DMA? Не понял что такое "4 DMA"? У Вас в первом сообщении написано про приём с UART посредством DMA, а всю переписку мне читать лень что там навыдумывали. Для приёма с UART посредством DMA в кольцевой буфер достаточно одного DMA канала. Так как в STM32, в силу его ущербности отсутствует UART-FIFO, а скорости UART Вы хотите большие, то перепрограммировать DMA на новую передачу при завершении предыдущей каждый раз опасно - можно не успеть запрограммировать DMA на очередную порцию и будет потеря байт. Поэтому нужно использовать работу DMA в режиме связных списков. В таком случае программирование следущей DMA-передачи будет идти не в конце предыдущей, а в начале. Не знаю как в STM32, но почти на всех МК с которыми я работал DMA-контроллер позволял работать в режиме связных списков. Условно говоря алгоритм следущий: 1. Программируем первый DMA-блок на приём в первую треть кольцевого буфера, второй DMA-блок программируем на приём во вторую треть кольцевого буфера. В первом блоке ставим ссылку на второй блок, во втором - на первый. В каждом блоке ставим флаг - выдать прерывание по окончании блока. 2. Запускаем DMA. 3. При получении первого прерывания (нечётного) знаем что сейчас закончился приём первого блока и начался приём 2-го блока. В этом ISR корректируем указатели целевого адреса и размера в первом блоке на следующее свободное место в кольцевом буфере (в первом полученном прерывании это будет 3-я часть кольцевого буфера) и выходим из ISR. 4. При получении второго прерывания (чётного) знаем что сейчас закончился приём 2-го блока и начался приём 1-го блока. Корректируем указатель и размер во 2-ом блоке. 5. .... и так далее опять с шага 3. На каждом полученном прерывании завершения DMA-блока корректируем след. блок определяя доступный размер непрерывного блока в циклическом буфере. Наверное даже лучше оперировать не двумя DMA-блоками, а тремя. Это на случай если текущий доступный блок в кольцевом буфере находится перед самым его концом и DMA-блок будет очень маленький, соответственно след. прерыванние можем получить очень быстро не успев запрограммировать след. блок. Ну и конечно необходимо ещё прерывание таймера, в котором отслеживаем состояние приёма текущего DMA-блока, обновляя указатель доступных данных в кольцевом буфере. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 3 декабря, 2015 Опубликовано 3 декабря, 2015 · Жалоба Не знаю как в STM32 ... ну очень плохо. Переименуйте ответ в "для сферического DMA в достаточно разреженной среде можно сделать вот так:", и всё будет хорошо. А для ST-шек оно не работает. Там и DMA не очень-то навороченный... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 3 декабря, 2015 Опубликовано 3 декабря, 2015 · Жалоба Переименуйте ответ в "для сферического DMA в достаточно разреженной среде можно сделать вот так:", и всё будет хорошо. А для ST-шек оно не работает. Там и DMA не очень-то навороченный... И что вы хотели этим сказать? Что кроме STM32 больше ничего не знаете? Такой алгоритм работает на любом DMA-контроллере с поддержкой связных списков, а реализована она по-разному в разных МК. Связные списки есть в DMA-контроллерах LPC разных линеек, в Tiva TM4C129, в OMAP-L137 и думаю многих других. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 4 декабря, 2015 Опубликовано 4 декабря, 2015 · Жалоба Это все теория...менять контроллер сейчас нет смысла. Я пока вот это никак отловить не могу. Теперь иногда вылазит такой баг - конец одного пакета как бы затирает начало первого. Еще раз обрисую ситуацию. Есть кольцевой буфер, на 512 байт. В него раз в 1,125 мс пишут 4 DMA. Размер одной посылки по DMA - 19 байт. Обработка прерывания одного DMA занимает примерно 22 мкс. Раз в 1 мс приходит запрос данных и если есть данные - они передаются по UART. Прерывания DMA и UART имеют одинаковый приоритет, поэтому вычисление количества данных и манипуляции с указателями выполняются вроде как атомарно. Смотрел осциллографом - скорость передачи такова, что частота опроса в 1 мс нормальна. Данные передаются самое большее где то за 0,5 - 0,6 мс. Тем не менее, по истечению какого то времени (минут 15-20) возникает непонятный баг - конец одного пакета затирает начало другого. И еще более странно, затирает не предыдущий пакет! Я добавил в начало и конец каждого пакета байтовый счетчик. Прикладываю скрин с этим багом, разложил все по пакетам. 7 пакетов, начало первого пакета затер конец 7-го пакета. Может быть у кого то есть идеи из-за чего такое может быть? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardEgor 83 4 декабря, 2015 Опубликовано 4 декабря, 2015 · Жалоба Это все теория...менять контроллер сейчас нет смысла. Я пока вот это никак отловить не могу. Вставить в каждое прерывание индикаторы срабатывания - в начале взводить какой-нибудь пин, в конце сбрасывать, По идее на пинах от разных прерываний будет периодический сигнал и многоканальным осциллографом или логическим анализатором ждать когда появятся несуразности с сигналами или перекрытие прерываний. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexashka 0 4 декабря, 2015 Опубликовано 4 декабря, 2015 · Жалоба Я пока вот это никак отловить не могу. Самое интересное, что индекс начала одного пакета 0, а другого 128. Можно было бы предположить, что гдето в индексе массива используется I8 вместо U16 или U32, но тогда бы эта ошибка вылезала каждый раз. Более того, чтобы получить две копии одного и того же пакета нужно дважды скопировать один массив в два места, что не возможно, если верить Вашей логике - для этого нужно дважды влететь в прерывание от ДМА, при этом второй раз там уже будет совсем другой пакет. У Вас точно не вложенные прерывания? И еще проверьте, чтобы не было функций, которые используются в прерывании и в основном теле. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 8 декабря, 2015 Опубликовано 8 декабря, 2015 · Жалоба Самое интересное, что индекс начала одного пакета 0, а другого 128. Можно было бы предположить, что гдето в индексе массива используется I8 вместо U16 или U32, но тогда бы эта ошибка вылезала каждый раз. Более того, чтобы получить две копии одного и того же пакета нужно дважды скопировать один массив в два места, что не возможно, если верить Вашей логике - для этого нужно дважды влететь в прерывание от ДМА, при этом второй раз там уже будет совсем другой пакет. У Вас точно не вложенные прерывания? И еще проверьте, чтобы не было функций, которые используются в прерывании и в основном теле. В какой уже раз при нарушении работы я ищу ошибку в STM32, а она на самом деле в C8051F320. У меня там задействован Endpoint 2, размер которого 256 байт и в дескрипторах объявлен размер эндпойнта 256 байт. Но еще включена двойная буферизация, поэтому писать в USB FIFO больше 128 байт нельзя, а я писал и 133 байта и 152, чаще 133. Причем никаких ошибок и наложений в большинстве случаев такой записи не было. Я не знаю, как работает FIFO и куда он пишет, если писать некуда. Но в какой то момент, видимо, при попытке записи больше, чем влезает он накладывал не вошедшие данные поверх уже записанных. Отсюда видимо и количество наложенных байт - 5, это не что иное как 133 - 128. Может кто-нибудь знает как работает USB FIFO у C8051F320 ? Еще, не знаю насколько это корректно, но я ограничил количество данных вычитываемых из кольцевого буфера. Посмотрел осциллографом - получалось так, что по запросу отправлялось 133 байта, а на следующий запрос - данных было мало или, чаще, совсем не было. В общем я добавил условие, что если вычисленная длина равна 133 байта (или больше), то присваиваем ей значение 114 (на один пакет меньше). Получается, я отправляю не сразу все готовые данные, а часть оставляю на потом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться