Обсуждаем контроллеры компании Atmel.
Ответить

Re: Нужна помощь по написанию функции на АСМе

Пт дек 23, 2016 06:55:28

COKPOWEHEU писал(а):Если хотите, могу выложить свою версию кольцевых буферов для UART'а.
да ни к чему это. проблемы сделать кольцо нет никакой, проблема с осознанием необходимости этого.
ваши экзотические задачи попадают в те проценты, когда я не возражаю против буферизации :)))

Re: Нужна помощь по написанию функции на АСМе

Пт дек 23, 2016 11:52:54

ARV писал(а):проблема с осознанием необходимости этого.

А ее нет. И никто, кроме Вас о необходимости не говорил не слова.
Любая проблема имеет, как минимум, два решения. В описываемом случае, кольцевой буфер является одним из этих вариантов решения.
Можно сравнивать эффективность нескольких вариантов решения. Делается табличка достоинств и недостатков каждого решения. Варианты решения в заголовках столбцов. Анализируемые характеристики решений - в строках. Проставляем баллы по каждому пункту, во всех колонках, в зависимости от важности этой характеристики в данном случае. По сумме баллов определяем, какое решение эффективней.

Re: Нужна помощь по написанию функции на АСМе

Пт дек 23, 2016 20:35:26

ptr128 писал(а):
AQ29 писал(а):Следящая схема, в которой МК, например, раз в секунду по прерыванию таймера вырабатывает управляющий сигнал. А в перерывах МК выполняет какую-нибудь программу, где необходима задержка, скажем, на 10 мсек.

Налицо ошибка проектирования. Ведь никто не мешал таймером всегда считать промежутки по 1мс, обеспечивая каждые тысячу отсчетов (раз в секунду) обработку управляющего сигнала. Зато любой процесс в МК имел бы возможность выполнить паузу любой продолжительностью, кратной 1мс.

Не вижу ошибки проектирования. Более того, на мой взгляд, моё решение для такой задачи лучше. У меня во второй задаче элементарно сделать любую задержку независимо от таймера. Это удобно. Ведь может потребоваться задержка, скажем, 131 мксек или 217 мксек, может потребоваться варьировать задержкой по ситуации. В первой задаче таймер может быть задействован под другие задачи, например, ШИМ, и т. д. В моём решении это просто делается.
ptr128 писал(а):
AQ29 писал(а):В большинстве случаев в программе обработки прерывания только устанавливаю программный флаг.

Очень упрощенный подход. Кольцевой буфер сообщений гибче и надежней.

Вообще-то простые решения часто бывают надёжней.
Про кольцевой буфер надо ознакомиться, возможно, включу в свой арсенал.
ptr128 писал(а):
AQ29 писал(а):Для точной задержки прерывание можно запретить, тогда задержка с циклами будет выполняться с точностью до одного такта.

Вот именно про это я и говорю! Что точную задержку циклом Вы сделаете только ценой монополии на CPU, что ни в какие ворота не лезет.

На мой взгляд, в некоторые «ворота вполне лезет».
Скажем, пример из практики. Периферийный МК для управления силовым ключом вырабатывает пачку импульсов. Длительность импульса жёстко определена. Длительность времени между импульсами пачки варьируется для подстройки частоты на резонанс.
Вот во время пачки и делаю запрет на прерывания.
А в паузах между пачками разрешаются прерывания и производится обмен данными с центральным МК и другие прочие дела.

scorpi_0n писал(а):Соглашусь с АРВ. Если нужны мгновенные реакции на внешние события или задержки с точностью до такта, то АВР действительно не та платформа. Задержки на циклах имеют право на жизнь только в одном случае - начальная инициализация каких-то устройств.

Не замечал, что АВР медленно реагирует на внешние события. И с задержками с точностью до такта не встречал особых проблем.
Как и у ARV, у меня в проектах задержки на циклах - большинство, возможно, даже более 80 %, правда, самопальных, в АБ нет библиотек.
ptr128 писал(а):Можно сравнивать эффективность нескольких вариантов решения. Делается табличка достоинств и недостатков каждого решения. Варианты решения в заголовках столбцов. Анализируемые характеристики решений - в строках. Проставляем баллы по каждому пункту, во всех колонках, в зависимости от важности этой характеристики в данном случае. По сумме баллов определяем, какое решение эффективней.

А баллы как выбираются, согласно личным впечатлениям или по какой-нибудь методике?

Re: Нужна помощь по написанию функции на АСМе

Сб дек 24, 2016 00:46:08

AQ29 писал(а):Следящая схема, в которой МК, например, раз в секунду по прерыванию таймера вырабатывает управляющий сигнал. А в перерывах МК выполняет какую-нибудь программу, где необходима задержка, скажем, на 10 мсек.

ptr128 писал(а):Налицо ошибка проектирования. Ведь никто не мешал таймером всегда считать промежутки по 1мс, обеспечивая каждые тысячу отсчетов (раз в секунду) обработку управляющего сигнала. Зато любой процесс в МК имел бы возможность выполнить паузу любой продолжительностью, кратной 1мс.

AQ29 писал(а):Не вижу ошибки проектирования.
Ведь может потребоваться задержка, скажем, 131 мксек или 217 мксек

Поясняю. Проектирование программ с задержками в 10 миллисекунд и 130 микросекунд (разница в 2 порядка) выполняется по разному.
В крайнем случае, никто не запрещает иметь унифицированный программный таймер, осуществляющий задержку на любое количество тактов средствами аппаратного таймера до окончания ближайшей по времени запрошенной задержки. Именно так это и сделано на ПК, где таймер только один.
Представить себе необходимость задержек с точностью свыше +-1% я не могу. То есть, в новом случае, таймер на частоте в 8МГц и сбросом при каждые 96 значений даст нам отсчет в 12 мкс.
12*11=132мкс, 12*18=216мкс

AQ29 писал(а):
ptr128 писал(а):точную задержку циклом Вы сделаете только ценой монополии на CPU, что ни в какие ворота не лезет.

На мой взгляд, в некоторые «ворота вполне лезет».

Очень частный случай. Давайте все же считать общим случаем то, с чего начинали. Когда Вы уже используете все три таймера, а значит в Вашей программе может происходить не одно, а не меньше трех асинхронных событий.

AQ29 писал(а):А баллы как выбираются, согласно личным впечатлениям или по какой-нибудь методике?

ptr128 писал(а):Проставляем баллы по каждому пункту, во всех колонках, в зависимости от важности этой характеристики в данном случае.

Re: Нужна помощь по написанию функции на АСМе

Сб дек 24, 2016 13:19:46

ptr128 писал(а): Примитивная поддержка мультизадачности появилась только на 386. Полноценная - существенно позднее.
анекдот, правда, уже старый.
сын у Гейтса спрашивает:
- папа, правда, что твоя Виндоус - многозадачная?
- правда, сынок.
- а покажи!
- подожди немножко, только закончу дискеты форматировать.

Re: Нужна помощь по написанию функции на АСМе

Сб дек 24, 2016 14:39:42

ARV писал(а):ваши экзотические задачи попадают в те проценты, когда я не возражаю против буферизации :)))
Любая работа с
низкоскоростными интерфейсами попадает в такие "экзотические задачи". Ну либо высчитывать такты чтобы программа гарантировано не пропустила событие и успела обработать остальные даже в худшем случае.

Re: Нужна помощь по написанию функции на АСМе

Сб дек 24, 2016 19:31:17

COKPOWEHEU писал(а):Любая работа
например, GPS: один раз в секунду передается пакет текстовых строк, максимальная длина строки ограничена 80 байтами. стандартная скорость передачи - 4800 бод, но сейчас чаще стандартно 9600, а можно настроить и на бОльшую скорость. так как всегда интересует какая-то конкретная строка из пакета, а не все подряд, требуется дождаться начала нужной строки, принять ее, и потом тупо игнорировать все данные - сколько бы их ни было! - в течение примерно 800-1000 миллисекунд. вы считаете, что эта задача как раз из тех "любых", которые просто невозможно решить без кольцевого буфера? простой линейный буфер в 80 байт, и никаких проблем! и никакого страха что-либо пропустить. кольцо не даст вообще никаких преимуществ в данном случае. если использовать достаточно высокую тактовую частоту МК, можно вообще без всяких буферов распарсивать приходящие данные на лету... но это уже на любителя острых ощущений.

я понимаю, что "любую" задачу можно так усложнить, что и не всякий ARM с нею справится, но надо ли? из числа любительских проектов, с которыми мне доводилось сталкиваться по необходимости или из любопытства, я не могу припомнить ни одного, где остро стояла бы проблема обработки данных UART-а. к чему доказывать обратное? сложная задача - сложное решение, простая задача - простое решение.

Re: Нужна помощь по написанию функции на АСМе

Сб дек 24, 2016 20:12:48

ARV писал(а):невозможно решить

ptr128 писал(а):Любая проблема имеет, как минимум, два решения.


ARV писал(а):простой линейный буфер в 80 байт

Что, например, для ATTiny2313 составит почти 2/3 доступной RAM

ARV писал(а):можно настроить и на бОльшую скорость

Больше 38400 мало какие SiRF поддерживают. Меньше 10 бит на байт не получится (1 старт, 1 стоп, 0 четности). Итого, нам надо забирать байты, в среднем, каждые 260мкс, с допустимой однократной максимальной задержкой не более 520мкс, благодаря однобайтной буферизации в UART. При частоте даже в 1МГц - это порядка 200 машинных команд. У меня получается, что даже на С, без ассемблера (хотя тема по ассемблеру!), за 200 команд можно не только полностью распарсить сообщение, но еще даже успеть начать что-то выводить по результатам его парсинга.

ARV писал(а):я не могу припомнить ни одного, где остро стояла бы проблема обработки данных UART-а

SPI на UART с частотой Fclk/2. В среднем 16 тактов на байт. Примерно 10-12 команд. Так как это SPI - то 10-12 команд и на отправку и на прием байта.

Re: Нужна помощь по написанию функции на АСМе

Сб дек 24, 2016 22:40:21

ARV писал(а):например, GPS
...
вы считаете, что эта задача как раз из тех "любых", которые просто невозможно решить без кольцевого буфера?
Где я писал что кольцевой буфер - единственное решение всех проблем? Впрочем, даже и так, его использование не навредит. Данные в любом случае надо принять и где-то хранить, а кольцевой буфер можно настроить чтобы он не игнорировал свежие данные, а перезаписывал ими старые.
А вообще-то кольцевой буфер (правильнее - очередь) используется для разделения приема данных, их обработки и передачи. Слой абстракции, драйвер, если хотите.
ARV писал(а):простой линейный буфер в 80 байт

Что, например, для ATTiny2313 составит почти 2/3 доступной RAM
А вот с этим ничего не поделаешь если надо хранить строку целиком. Реализовать парсинг "на лету" может оказаться еще сложнее.
У меня получается, что даже на С, без ассемблера (хотя тема по ассемблеру!), за 200 команд можно не только полностью распарсить сообщение, но еще даже успеть начать что-то выводить по результатам его парсинга.
Это если контроллер ничего другого не делает и если данные вообще возможно парсить на лету.

Re: Нужна помощь по написанию функции на АСМе

Сб дек 24, 2016 23:03:52

COKPOWEHEU писал(а):Это если контроллер ничего другого не делает и если данные вообще возможно парсить на лету.

200 команд на один принятый байт - очень много. Причем я считал для минимальной частоты 1МГц. Не для 16 и даже не для 8. Еще на пару прерываний команд по 50 хватит. Если конечно не преобразовывать здоровенные десятичные числа в двоичные. Но в данном случае такой необходимости явно нет. Даже без команды двоично-десятичной коррекции с упакованными десятичными числами на AVR вполне реально управляться.

Re: Нужна помощь по написанию функции на АСМе

Вс дек 25, 2016 01:13:38

Ну мы же сейчас обсуждаем сферических коней. Например, надо по строке с UART'а "Read_ADC_0" считать АЦП, преобразовать в 4-байтный float и вывести обратно, причем сам АЦП работает на максимальной частоте и усредняется. Собственно, сравнение строк уже достаточная причина использовать буфер, хотя бы линейный.
Более практическая задача - прием данных с упоминавшегося мной 4-канального АЦП e24. Он передает каждое значение четырьмя байтами, причем старший бит первого равен 1 а остальных - 0. Биты 4,5,6 первого байта используются для номера канала и состояние контакта. Иначе говоря, анализировать имеет смысл все 4 байта за раз, а не по одному.

Re: Нужна помощь по написанию функции на АСМе

Вс дек 25, 2016 07:57:34

COKPOWEHEU писал(а):Например, надо по строке с UART'а "Read_ADC_0" считать АЦП, преобразовать в 4-байтный float и вывести обратно, причем сам АЦП работает на максимальной частоте и усредняется.
я и говорил, что любую задачу можно так сформулировать, что ее и решить будет невозможно.

АЦП должно в фоне (по отношению к прерыванию-запросу - в фоне, хотя по логике работы это, вероятно, должен быть основной цикл) постоянно измерять и усреднять, преобразовывать во float, сохраняя где-то результат, а при получении вашей строки-запроса должно мгновенно браться уже готовое значение и выдаваться обратно.

Re: Нужна помощь по написанию функции на АСМе

Вс дек 25, 2016 09:56:16

COKPOWEHEU писал(а):Ну мы же сейчас обсуждаем сферических коней.

Вы, похоже, да :)))

Я обсуждаю cовершенно конкретную задачу парсинга данных GPS трекера на 38400 бодах ассемблером AVR при частоте CPU 1Мгц.

COKPOWEHEU писал(а):Например, надо по строке с UART'а "Read_ADC_0" считать АЦП, преобразовать в 4-байтный float и вывести обратно, причем сам АЦП работает на максимальной частоте и усредняется.

И впрямь "сферический конь". Какой смысл максимум 12-тибитное значение ADC преобразовывать на ассемблере в четырех байтный float только для того, чтобы потом опять на ассемблере преобразовывать его в десятичное для передачи по UART в строковом виде?
Если Вам нужна помощь в конкретной задаче, чтобы не пасти сферических коней в вакууме - опишите задачу, а не то, как Вы собираетесь ее решать.

Добавлено after 2 minutes 6 seconds:
ARV писал(а):преобразовывать во float

Зачем Вам float на ассемблере? Тем более для хранения 12-ти битного целого числа!

Re: Нужна помощь по написанию функции на АСМе

Вс дек 25, 2016 13:36:28

Про float и извращения с ним - из области сферических коней. У меня такой задачи не возникало.
Я обсуждаю cовершенно конкретную задачу парсинга данных GPS трекера на 38400 бодах ассемблером AVR при частоте CPU 1Мгц.

Задача ARV в 4 раза менее требовательна к скорости. С GPS дела не имел, но насколько только что прочитал, логично либо считывать всю строку в буфер (как делает ARV), либо считывать ее часть, достаточную для анализа фрагмента - строки описания, строки широты, долготы или времени. Но вот идея анализировать побайтно, вообще без буфера, не кажется особо удачной.
Какой смысл максимум 12-тибитное значение ADC преобразовывать на ассемблере в четырех байтный float только для того, чтобы потом опять на ассемблере преобразовывать его в десятичное для передачи по UART в строковом виде?
АЦП в AVR всего 10 бит. А у внешних может быть любой. Что до float'а, при достаточном диапазоне измерения (скажем, от микровольт до киловольт), переключаемым снаружи резистивными делителями или усилителями, для приемника может быть удобно получать значение вида 1.28e-3V. Разумеется, речь опять о сферических конях.

Re: Нужна помощь по написанию функции на АСМе

Вс дек 25, 2016 13:48:28

COKPOWEHEU писал(а):Что до float'а, при достаточном диапазоне измерения (скажем, от микровольт до киловольт), переключаемым снаружи резистивными делителями или усилителями, для приемника может быть удобно получать значение вида 1.28e-3V. Разумеется, речь опять о сферических конях.

Что Вам мешает внутри МК оперировать милливольтами или вообще абстрактными "попугаями" целочисленной арифметикой, а уже пользователю выводить данные в удобном ему виде?
Особенно на ассемблере AVR, для которого float совершенно чуждое и инородное понятие.

Если в четырех байтах, которые занимает float, разместить целый uint32_t, то он в микровольтах позволит Вам оперировать со значениями до 4 киловольт.
А значит, только в том случае, когда разница между максимальным и минимальным измерямым значением превышает 4 миллиарда, только тогда оправдано применение float

Re: Нужна помощь по написанию функции на АСМе

Вс дек 25, 2016 17:36:38

Посмотрите, пожалуйста, мой первый опыт по скрещиванию Си и ассемблера AVR
Функция инкремента двоично-десятичного числа - при компилировании в Atmel Studio 7 получаю ворох ошибок.

Код:
uint8_t BCDinc(uint8_t i)
{
   uint8_t   res;
   uint8_t corr=6;
   asm volatile (
      "mov %res, %i"            "\n\t"   \
      "inc %res"               "\n\t"   \
      "brhc label1%="            "\n\t"   \
      "add %res,%corr"         "\n\t"   \
      "label1%=:"               "\n\t"   \
      "nop"                  "\n\t"
   );
   return res;
}

Re: Нужна помощь по написанию функции на АСМе

Вс дек 25, 2016 18:11:25

prinv писал(а):Функция инкремента двоино-десятичного числа

Алгоритм не верен. После инкремента мы должны контролировать не только наличие переноса между полубайтами, но еще и то, что в младшем полубайте не возникло значения большего 9. Точнее, если у нас уже было корректное двоично-десятичное число, то перенос между полубайтами вообще при инкременте не может возникнуть, а вот 0x9 в младшем полубайте просто обязан превратиться в 0xA.
Довольно неплохая статейка по этому поводу тут: http://imrannazar.com/Binary-Coded-Deci ... -Atmel-AVR

prinv писал(а):при компилировании получаю ворох ошибок.

С этим проще. Но исправленный код по вышеописанной причине работать не будет.
Осторожней с табуляцей! Для ассемблера она может иметь свой сакральный смысл.
Код:
uint8_t BCDinc(uint8_t i)
{
   uint8_t   res;

  asm volatile ( ";         \n\t \
    mov   %[res], %[i]      \n\t \
    inc   %[res]            \n\t \
    brhc  label1%=          \n\t \
    add   %[res],%[corr]    \n \
  label1%=:                 \n\t \
    nop                     \n \
  "
  : [res] "=r" (res)
  : [i] "r" (i), [corr] "r" (6)
  : "cc" );
   return res;
}

Ассемлер и С друг друга не видят. Вся коммуникация между ними описывается в трех предложениях, разделенных двоеточиями после строки ассемблерного кода.
Первое предложение есть список всех модифицируемых в С переменных. В нашем случае переменная res. = обозначает, что текущее значение переменной из С в ассемблер передавать не требуется и операнд используется только для возврата значения. Был бы + то, считалось бы, что значение переменной модифицируется и ее текущее значение было бы передано. r обозначает, что значение должно быть размещено в любом из регистров
Второе - входные параметры. Передаем значение i и corr, размещая их в регистрах. corr можно задавать константой.
Третье - используемые регистры. В коде модифицируется только регистр флагов, потому только его и указываем.

Подробности тут: http://www.nongnu.org/avr-libc/user-man ... e_asm.html

Re: Нужна помощь по написанию функции на АСМе

Вс дек 25, 2016 18:22:57

Большое спасибо! Алгоритм сейчас откатаю, проблема была со вставкой ассемблера.

Re: Нужна помощь по написанию функции на АСМе

Вс дек 25, 2016 18:38:07

Что Вам мешает внутри МК оперировать милливольтами или вообще абстрактными "попугаями" целочисленной арифметикой, а уже пользователю выводить данные в удобном ему виде?
Особенно на ассемблере AVR, для которого float совершенно чуждое и инородное понятие.
Сколько еще раз мне повторить что у меня такой задачи не возникало, я ее привел только в качестве примера?
Посмотрите, пожалуйста, мой первый опыт по скрещиванию Си и ассемблера AVR
Читайте документацию по avr-libc. Там есть и ассемблерные вставки и использование файлов ассемблерного кода средствами gcc (точнее, gnu-as + ld). В том числе, какие регистры программист обязан сохранять, а какими занимается gcc.

Re: Нужна помощь по написанию функции на АСМе

Пн дек 26, 2016 20:12:03

Код:
Довольно неплохая статейка по этому поводу тут: http://imrannazar.com/Binary-Coded-Deci ... -Atmel-AVR
Может кто обьяснить, зачем в приведённой статье используется регистр R18 и как в регистре R16 получается результат, если в финале POP16, те опять имеем входное BCD? Убрать POP16? (и PUSH в начале?) Просто мне актуально, как раз над этим ломаю голову.
Ps это в разделе "AVR implementation of DAA"
Ответить