Tolmi писал(а):А число обязательно переводить во float ? Подозреваю, что работа с long long int всё же быстрее, чем эмуляция плавающей точки.
long long нету В недосреде CVAVR ограничение в 32бита.
Надо 8 байтовое число с фиксированной запятой (e-6) перевести в текстовый вид.
Проблему решил просто загнав поочереди первые и вторые 4 байта во float. Вторые 4 байта умножил на 4294967295. А уже потом разделил на 1000000.
Тогда точность не теряется.
demiurg301 писал(а):long long нету В недосреде CVAVR ограничение в 32бита.
Надо 8 байтовое число с фиксированной запятой (e-6) перевести в текстовый вид.
Проблему решил просто загнав поочереди первые и вторые 4 байта во float. Вторые 4 байта умножил на 4294967295. А уже потом разделил на 1000000.
Тогда точность не теряется.
Ух ты. А ради чего? Ради недосреды? Может, пора мигрировать? Как в том анекдоте, "хоть тушкой, хоть чучелом - а ехать надо".
Осваиваю использование Си и Асм в одном проекте в AVRStudio+GCC.....
На асме написано скоростное прерывание. Реально скоростное - частота вызова 250 000 Гц.....
Поэтому для обработки в прерывании использую несколько переменных, размещенных в регистрах.
Первоначально объявляю их в Си, потом инициализирую значениями, потом разрешаю прерывания.....
Саму совместную работу Си и Асм - победил.... НО есть нюанс!
#define F_CPU 9600000
#include <avr/io.h>
volatile register uint8_t var asm("r2");
int main (void)
{
var = 100;
sei();
while(1){
}
}
В Си только объявляю и инициализирую переменную, потом она используется только в асмовом файле.... Так вот компилятор ее начисто вырезает (т.е. ничего не грузит в r2), хотя вроде объявил volatile.....
Так вы изначально объявили регистр как не позволительный для работы оптимизатора. Как он может быть уверен, что вы ничего не положили в этот регистр?
Есть ведь возможность использовать компилятор не запрещая ему использовать регистры в дальнейшем.
Посмотрите в тех же библиотеках как это сделано.
Можно в самой функции указать в какой регистр поместить входные данные и после вычисления из какого регистра куда положить результат.
К сожалению пример показать не могу, там немного мудрено выглядит наподобие функции printf.
Короче как обычно читать мануалы - это наше все. вот тут можно почитать.
vitalik_1984 писал(а):Так вы изначально объявили регистр как не позволительный для работы оптимизатора. Как он может быть уверен, что вы ничего не положили в этот регистр?
Не понял, что вы хотели сказать.....
vitalik_1984 писал(а):Есть ведь возможность использовать компилятор не запрещая ему использовать регистры в дальнейшем.
Но эти регистры как раз и являются глобальными переменными... как я могу разрешить компилятору в дальнейшем их использовать.... (я так понял, что вы имеете ввиду - использование по усмотрению самого компилятора)
vitalik_1984 писал(а):Можно в самой функции указать в какой регистр поместить входные данные и после вычисления из какого регистра куда положить результат. Короче как обычно читать мануалы - это наше все. вот тут можно почитать.
Вы наверное ведете речь о ассемблерных вставках.... А я говорю о функции отдельно и целиком на ассемблере с последующим вызовом ее из С
Вот... шо называется найдите отличия:
Тут компиль вырезает загрузку в r2, хотя вроде volatile.....
vitalik_1984 писал(а):Да интересная картина.
Пробовали с другими регистрами так же?
Вообще это я для простоты пример привел, а так у меня 5 регистров под переменные бронируется, r2 - r6.....
Эти регистры можно использовать под такое дело, вот выдержка отсюда: http://www.nongnu.org/avr-libc/user-man ... aq_regbind
How to permanently bind a variable to a register?
This can be done with
register unsigned char counter asm("r3");
Typically, it should be safe to use r2 through r7 that way.
Registers r8 through r15 can be used for argument passing by the compiler in case many or long arguments are being passed to callees. If this is not the case throughout the entire application, these registers could be used for register variables as well.
Попробовал отключить оптимизацию, нормально получается, все как надо работает, но размер процентов на 50 возрастает, чего тоже не очень охота.....
Интересно а нельзя как то отключить оптимизацию, на участке кода где эти переменные объявляются... а потом опять включить?
vitalik_1984 писал(а):Либо использовать эту переменную в прерывании хотя бы чтобы понятно было.
В прерывании эти переменные как раз и используются, правда прерывание на асме, и видимо из за этого сишный оптимизатор не видит их использования.....
А инлайн чего не хотите попробовать? Вроде как описывается как более мощный инструмент, чем просто вставки. Или как у вас там сделаны прерывания?
Почему бы на ассемблере не загрузить ваше значение?
Последний раз редактировалось vitalik_1984 Чт май 16, 2013 01:58:58, всего редактировалось 1 раз.
Теперь компиль теоритически думает что переменные задействованы, и нормально их инициализирует.....
Фактически же этот кусок кода никогда не будет использоваться... (короче.. не нытьем так катаньем.....)
Зато и оптимизация осталась, и размер кода вырос не на много, только на размер этого фрагмента
Пока боле менее нормального варианта не найду, так оставлю.....
А что сама идея быстродействия разбивается о скалы бесполезного счетчика и ненужного сравнения вас не тревожит?
Может тогда так?
PORTB = Div5 = Div250 = TimerL = TimerH= Flags=(тут нужное значение для порта B);
Последний раз редактировалось vitalik_1984 Чт май 16, 2013 02:08:11, всего редактировалось 1 раз.
vitalik_1984 писал(а):А инлайн чего не хотите попробовать? Вроде как описывается как более мощный инструмент, чем просто вставки. Или как у вас там сделаны прерывания?
Пробовал инлайнить Сишную процедуру.....
Но результат не устраивает.
Во первых прерывание сохраняет в стеке в 2 раза больше регистров чем я на асме...
Во вторых Си вместо обычного:
dec r2
вставляет:
mov r24,r2
subi r24,254
mov r2,r24
каково?.....
В третьих, это моя давняя мечта была, освоить вызов из Си ассемблерных модулей.... кажется получилось.....
Теперь можно и на Си делать экстремальные вещи.....
В общем мой обработчик прерывания такой получился:
vitalik_1984 писал(а):Почему бы на ассемблере не загрузить ваше значение?
Загрузить то я могу на асме, НО, суть в том чтобы Си заставить отвести эти регистры чисто для моих переменных, ведь они там все время жизни находятся..... Если Си не заставить этого сделать, то он может их испортить, используя эти регистры по своему усмотрению.....
vitalik_1984 писал(а):А что сама идея быстродействия разбивается о скалы бесполезного счетчика и ненужного сравнения вас не тревожит?
Так я же сказал, что этот код никогда не запустится, ну будет одно сравнение, которое никогда не будет истинным, но это в майне, там мне и не нужно особое быстродействие..... оно нужно именно в прерывании, т.к. 250000Гц это не шуточки.....
vitalik_1984 писал(а):Может тогда так?
PORTB = Div5 = Div250 = TimerL = TimerH= Flags=(тут нужное значение для порта B);
Во первых мне и не нужно это значение, т.к. в порт ничего и не выводится.... во вторых у меня эти переменные инитятся разными значениями, а так как вы предложили, они все проинитятся одним числом.....
vitalik_1984 писал(а):Я про инлайн ассемблер. Проходили по ссылке, что я вам дал?
По ссылке проходил, честно говоря от инлайнового асма у меня голова кружится....слишком перегружен синтаксис.....
Хотя, можно попробовать и такой вариант. Единственное, вызов прерывания в моем случае полностью подконтролен мне, т.е. с первой команды обработчика я управляю процессом..... а в случае инлайнового обработчика, вызов будет обрабатыватся компилятором, и только после того как он насохраняет кучу регистров в стеке, я смогу получить доступ для инлайновых асмо команд.....
vitalik_1984 писал(а):Вы ведь сами код пишете на асме, каким образом получится вместо обычного: dec r2.......
я там чуть не точно описал..... НО, реально.... компиль инкрементирует переменную - 1) вызовом значения в верхний регистр, 2) отнимая от него число 255, 3) загружая опять на место.....
vitalik_1984 писал(а):Почитал тут немного еще раз:
asm [volatile] («команды и директивы ассемблера» : выходные параметры : входные параметры : изменяемые параметры);
может нужно еще после asm volatile поставить?
Ну это опять же для инлайнового варианта, у себя пробовал по разному ставить, результат тот же.....
shads писал(а):Вот и вопросик, Почему компиль оптимизирует volatile выражение?.....
Компилятор "вычищает" его потому что содержимое его нигде не используется.
Добавьте __attribute__ ((used)) в определение.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
там же написано про несколько портов (один из которых имеет неполную реализацию в железе), а в примере один порт. Единственное, что грозит в этом случае это "The compiler stands no chance to optimize". В случае поочередного присваивания выполняется меньше инструкции, чем в случае присваивания в одной строке.
shads писал(а):Вот и вопросик, Почему компиль оптимизирует volatile выражение?.....
Компилятор "вычищает" его потому что содержимое его нигде не используется.
Добавьте __attribute__ ((used)) в определение.
Не...... не катит.....
И еще один момент.. по идее в ассемблерном файле я должен видеть сишные переменные, объявляя их напрмер так: .extern Div5
А НЕВИЖУ.....
из за этого вынужден либо напрямую работать с регистрами, либо обзывая регистры повторно в ассм файле...