Буфер приема сообщений
- Войдите на сайт для отправки комментариев
Сб, 23/04/2016 - 15:48
Имеется сеть контроллеров связанных по CAN шине. Пока пакеты влезали в 1 кадр (8 байт) все хорошо работало. Но сейчас нужно добавить пакеты больших размеров, вплоть до 10-20 кадров. Одним буфером уже не обойтись, ведь пакет может быть фрагментирован и нет гарантий, что все кадры придут подряд, а не в перемешку с другими.
На языке высокого уровня никакой проблемы нет, создается динамический буфер на каждый пакет.
Но как быть с Arduino? Я так понимаю динамических массивов тут нет...
PS
Кадры уже содержат в себе информацию о длине и порядковом номере каждого в общем пакете.
Вопрос именно о том, как и куда собирать кадры до того как будет готов весь пакет...
Динамические массивы в Arduino IDE есть, вы просто плохо искали: new/delete, malloc/free.
Если количество кадров ограничено разумным значением, как упомянуто, 20 шт, то лучше сделать массив фиксированного размера на максимальное кол-во кадров. Т.е. 20*8=160 байт + заголовки кадров (я не знаю сколько). В этом случае можно запонять массив сразу кадрами в своё место, значительно меньше ресурсов на управление динамической памятью. Собственно, эти несчастные 2-3, или 32 кб памяти делить динамически вообще как-то неловко даже. :)
DIYMan спасибо, посмотрю!
faeton в момент приема одного длинного папкета могут прийти кадры входящие в другой пакет. Когда "пакет = 1 кадр" это небыло проблемой, т.к. сразу после приема он шел на обработку, а сейчас сначала нужно собрать целый пакет!
DIYMan спасибо, посмотрю!
faeton в момент приема одного длинного папкета могут прийти кадры входящие в другой пакет. Когда "пакет = 1 кадр" это небыло проблемой, т.к. сразу после приема он шел на обработку, а сейчас сначала нужно собрать целый пакет!
И собирайте их в статическом массиве размером в максимальный размер кадра, ведь немного же. Вам всё равно понадобится либо цепочка указателей на выделенные куски памяти, либо массив указателей на те же куски, но размер самих указателей соизмерим с размером кадра.
На языке высокого уровня никакой проблемы нет, создается динамический буфер на каждый пакет.
Что Вы понимаете под "языком высого уровня"? Пример такого языка можете привести?
Но как быть с Arduino? Я так понимаю динамических массивов тут нет...
В ардуино вообще ничего нет, кроме платы с ногами и разъёмом USB, а вот в языке С++ (вернее, в его диалекте, который используется ардуино) динамические массивы есть. Пользуйтесь на здоровье. Только боюсь, они Вам не помогут.
Кадры уже содержат в себе информацию о длине и порядковом номере каждого в общем пакете.
Длине всего пакета? Т.е. длину пакета мы знаем сразу? ну, тогда вообще нет проблем, хоть динамический массив, хоть кусок памяти, запрошенный malloc. Только про фрагментацию не забывайте.
Кадры уже содержат в себе информацию о длине и порядковом номере каждого в общем пакете. Вопрос именно о том, как и куда собирать кадры до того как будет готов весь пакет...
... кадры от разных пакетов .. (промелькнуло)
1. Пакет состоит из кадров.
2. Кадры имеют фиксированный размер (8байт) .. или разный размер, но известный заранее? .. или приходящий кадр "имеет в себе" инфу про свой размер и место в пакете, то есть "до" его приема сказать за размер ничего нельзя?
3. Кадры одного пакета могут прийти в "перемежку" или от разных пакетов? То есть сколько принимаем пакетов единомоментно? То есть сколько пакетов может находится в процессе сборки, ожидая свои кадры?
Вариант реализации сильно зависит от ответов на эти вопросы. Чем больше ограничений - тем проще. Если в самом общем случае, то рекомендую посмотреть сетевые драйвера и программки из модели OSI (кажется так зовется) .. не ко мне, ибо уже деталей не помню. Но без malloc() в обшем виде врядли обойдетесь со всеми его прелестями и недостатками тут.
Если в самом общем случае, то рекомендую посмотреть сетевые драйвера и программки из модели OSI (кажется так зовется)
Они в аврках не поддерживают фрагментацию TCP, ибо затратно очень. Они даже пинг не полностью поддерживают - не всё назад возвращают, а пинг может 65кБ попросить прогнать.
да
фиксированные 8 байт. да в первом кадре, если будут другие содержится информация о номере текущего кадра и общем их количестве.
Порядок прихода кадров одного пакета не думаю, что может нарушится, но между ними могут приходить другие кадры. Не могу сказать сколько пакетов может одновременно собиратся, ну до 5шт я думаю. Часть кадров может теряться.
Причем при приеме 1 фрейма фрагментированного пакета так же записывается таймштамп, для контроля срока годности пакета, если при не успели собрать пакет до окончания срока годности, то чистим буфер. Если приходят фреймы (2 и последующие) при отсутвующем 1 фрейме в буфере, то игнорируем их.
в среде ардуино испольщован тоже язык высокого уровня. но дело здесь не в языке. Дело в том, что ардуино не компьютер и ресурсов здесь на порядки меньше, а значит надо более тщательно продумывать их использование. В той же UNO всего 2к оперативной памяти
Я бы не рекомендовал использовать динамическое выделение памяти. Надо выделить свою "кучу" и все что нужно складывать в нее
В качестве кучи может быть массив структур. В самом простом случае если мы принимаем один пакет и сортированные фрагменты - мы укладываем их в массив где индекс массива определяет номер фрагмента в пакете. Если же фрагменты не сортированы и/или одновременно могу приходить разные пакеты то тогда структуры надо делать связанными по отдельному полю, которое будет указывать индекс следующего фрагмента
Я бы предложил такую (де)композицию:
1. Структура 1 кадра. 8 байт, как понимаю у них есть свое "назначение" .. там, длина, контрольная сумма "метка времени"..
2. "пакет" - массив таких структур максимального размера для приема одного пакета. Дополнительно можно снабдить описаниями всего пакета .. метка времени сборки, к примеру или "размер пакета в кадрах" .. если макс=20 кадров, то это потребует 160 или чуть более байт на пакет. Пусть даже 200.
3. Буфер приема - как массив пакетов максимального размера. Для 5-10 принимаемых пакетов это даст 0.8-1 кб требуемой оперативы.
Теоретически, наверное можно будет впихнуть и в УНО, но лучше сразу затачиваться под Мегу с её 8кб или аналогичный МК, но с меньшими прочими ресурсами или с интерфейсом внешней SRAM (Atmega128A в частности - сейчас около 50руб/шт на Алиэкспрессе).
Для уменьшения требований к памяти можно ограничиться единым буфером кадров, скажем на 3 пакета по 10 кадров (наиболее ожидаемые величины) и создать тогда доп. массивы данных для учета инфы про текущие кадры для текущих пакетов сборки: какие кадры к ним относятся и где лежат в буфере кадров .. этакая "собственная куча для кадров". Тут повышение эффективности возможно из знания фиксированного размера кадра и переводу "указательной" арифметики к байтовой для индексов массива кадров.
Как-то так.