Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
demiurg301
Опытный кот
Сообщения: 812
Зарегистрирован: Ср мар 18, 2009 21:14:33

Re: Вопросы по С/С++ (СИ)

Сообщение demiurg301 »

Tolmi писал(а):А число обязательно переводить во float ? Подозреваю, что работа с long long int всё же быстрее, чем эмуляция плавающей точки.


long long нету :))) В недосреде CVAVR ограничение в 32бита. :))
Надо 8 байтовое число с фиксированной запятой (e-6) перевести в текстовый вид.
Проблему решил просто загнав поочереди первые и вторые 4 байта во float. Вторые 4 байта умножил на 4294967295. А уже потом разделил на 1000000.
Тогда точность не теряется.
Реклама
ut1wpr
Вымогатель припоя
Сообщения: 581
Зарегистрирован: Ср янв 05, 2011 10:03:18

Re: Вопросы по С/С++ (СИ)

Сообщение ut1wpr »

demiurg301 писал(а):long long нету :))) В недосреде CVAVR ограничение в 32бита. :))
Надо 8 байтовое число с фиксированной запятой (e-6) перевести в текстовый вид.
Проблему решил просто загнав поочереди первые и вторые 4 байта во float. Вторые 4 байта умножил на 4294967295. А уже потом разделил на 1000000.
Тогда точность не теряется.
Ух ты. А ради чего? Ради недосреды? Может, пора мигрировать? Как в том анекдоте, "хоть тушкой, хоть чучелом - а ехать надо". :)
С уважением,
Виктор.
Реклама
demiurg301
Опытный кот
Сообщения: 812
Зарегистрирован: Ср мар 18, 2009 21:14:33

Re: Вопросы по С/С++ (СИ)

Сообщение demiurg301 »

ut1wpr писал(а):Ух ты. А ради чего? Ради недосреды? Может, пора мигрировать? Как в том анекдоте, "хоть тушкой, хоть чучелом - а ехать надо". :)


К тому, что уже есть проект и надо пилить там , где он есть.
Переезжать то надо, но не всё сразу :)))
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Вопросы по С/С++ (СИ)

Сообщение shads »

Осваиваю использование Си и Асм в одном проекте в 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.....

Как с ним можно договорится?.....
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение vitalik_1984 »

Так вы изначально объявили регистр как не позволительный для работы оптимизатора. Как он может быть уверен, что вы ничего не положили в этот регистр?
Есть ведь возможность использовать компилятор не запрещая ему использовать регистры в дальнейшем.
Посмотрите в тех же библиотеках как это сделано.
Можно в самой функции указать в какой регистр поместить входные данные и после вычисления из какого регистра куда положить результат.
К сожалению пример показать не могу, там немного мудрено выглядит наподобие функции printf.
Короче как обычно читать мануалы - это наше все.
вот тут можно почитать.
Реклама
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Вопросы по С/С++ (СИ)

Сообщение shads »

vitalik_1984 писал(а):Так вы изначально объявили регистр как не позволительный для работы оптимизатора. Как он может быть уверен, что вы ничего не положили в этот регистр?
Не понял, что вы хотели сказать.....

vitalik_1984 писал(а):Есть ведь возможность использовать компилятор не запрещая ему использовать регистры в дальнейшем.
Но эти регистры как раз и являются глобальными переменными... как я могу разрешить компилятору в дальнейшем их использовать.... (я так понял, что вы имеете ввиду - использование по усмотрению самого компилятора)

vitalik_1984 писал(а):Можно в самой функции указать в какой регистр поместить входные данные и после вычисления из какого регистра куда положить результат. Короче как обычно читать мануалы - это наше все.
вот тут можно почитать.
Вы наверное ведете речь о ассемблерных вставках.... А я говорю о функции отдельно и целиком на ассемблере с последующим вызовом ее из С


Вот... шо называется найдите отличия:

Тут компиль вырезает загрузку в r2, хотя вроде volatile.....

Код: Выделить всё

#include <avr/io.h>

volatile register uint8_t var asm("r2");

int main (void)
{
    var = 100;
    while(1){
    }
}


00000022 <main>:
#include <avr/io.h>

volatile register uint8_t var asm("r2");

int main (void)
{
  22:    ff cf           rjmp    .-2          ; 0x22 <main> 



А тут нормально.....

Код: Выделить всё

#include <avr/io.h>

volatile register uint8_t var asm("r2");

int main (void)
{
    var = 100;
    while(1){
        PORTB = var++;
    }
}


00000022 <main>:

volatile register uint8_t var asm("r2");

int main (void)
{
    var = 100;
  22:    84 e6           ldi    r24, 0x64    ; 100
  24
:    28 2e           mov    r2, r24
    while
(1){
        PORTB = var++;
  26:    28 ba           out    0x18, r2    ; 24
  28
:    23 94           inc    r2
  2a
:    fd cf           rjmp    .-6          ; 0x26 <main+0x4> 


Вот и вопросик, Почему компиль оптимизирует volatile выражение?.....
Реклама
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение vitalik_1984 »

Да интересная картина.
Пробовали с другими регистрами так же?
Либо использовать эту переменную в прерывании хотя бы чтобы понятно было.
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Вопросы по С/С++ (СИ)

Сообщение shads »

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 возрастает, чего тоже не очень охота.....

Интересно а нельзя как то отключить оптимизацию, на участке кода где эти переменные объявляются... а потом опять включить? :shock:


vitalik_1984 писал(а):Либо использовать эту переменную в прерывании хотя бы чтобы понятно было.
В прерывании эти переменные как раз и используются, правда прерывание на асме, и видимо из за этого сишный оптимизатор не видит их использования.....
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение vitalik_1984 »

А инлайн чего не хотите попробовать? Вроде как описывается как более мощный инструмент, чем просто вставки. Или как у вас там сделаны прерывания?
Почему бы на ассемблере не загрузить ваше значение?
Последний раз редактировалось vitalik_1984 Чт май 16, 2013 01:58:58, всего редактировалось 1 раз.
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Вопросы по С/С++ (СИ)

Сообщение shads »

Гы.....

Обдурил пока что компилятор таким образом... вставил в майне кусок кода:

Код: Выделить всё

    static char NoOptim;
    if (++NoOptim == 2)
        NoOptim = 0;
    if (NoOptim == 255){
        PORTB = Div5++;
        PORTB = Div250++;
        PORTB = TimerL++;
        PORTB = TimerH++;
        PORTB = Flags++;
    }
 

Теперь компиль теоритически думает что переменные задействованы, и нормально их инициализирует.....
Фактически же этот кусок кода никогда не будет использоваться... (короче.. не нытьем так катаньем.....)
Зато и оптимизация осталась, и размер кода вырос не на много, только на размер этого фрагмента

Пока боле менее нормального варианта не найду, так оставлю.....
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение vitalik_1984 »

А что сама идея быстродействия разбивается о скалы бесполезного счетчика и ненужного сравнения вас не тревожит?
Может тогда так?
PORTB = Div5 = Div250 = TimerL = TimerH= Flags=(тут нужное значение для порта B);
Последний раз редактировалось vitalik_1984 Чт май 16, 2013 02:08:11, всего редактировалось 1 раз.
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Вопросы по С/С++ (СИ)

Сообщение shads »

vitalik_1984 писал(а):А инлайн чего не хотите попробовать? Вроде как описывается как более мощный инструмент, чем просто вставки. Или как у вас там сделаны прерывания?
Пробовал инлайнить Сишную процедуру.....
Но результат не устраивает.
Во первых прерывание сохраняет в стеке в 2 раза больше регистров чем я на асме...
Во вторых Си вместо обычного:
dec r2
вставляет:
mov r24,r2
subi r24,254
mov r2,r24
каково?.....
В третьих, это моя давняя мечта была, освоить вызов из Си ассемблерных модулей.... кажется получилось.....
Теперь можно и на Си делать экстремальные вещи.....

В общем мой обработчик прерывания такой получился:

Код: Выделить всё

#include <avr/io.h>
.global TIM0_COMPA_vect

TIM0_COMPA_vect:
   //тут частота прохода 250 000 Гц
   sbi      _SFR_IO_ADDR (PORTB),4
   push   r16
   in      r16,_SFR_IO_ADDR (SREG)
   push   r16

   dec      r2
   brne   exit
   ldi      r16,5
   mov      r2,r16

   //тут частота прохода 50 000 Гц
   inc      r4
   brne   TmrEnd
   inc      r5
   brne   TmrEnd
   ldi      r16,0xff
   mov      r4,r16
   mov      r5,r16
TmrEnd:
   dec      r3
   brne   exit
   ldi      r16,250
   mov      r3,r16

   //тут частота прохода 200 Гц
   mov      r16,r6
   ori      r16,(1<<0)
   mov      r6,r16
exit:   
   pop      r16
   out      _SFR_IO_ADDR (SREG),r16
   pop      r16
   cbi      _SFR_IO_ADDR (PORTB),4
   reti
.end
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Вопросы по С/С++ (СИ)

Сообщение shads »

vitalik_1984 писал(а):Почему бы на ассемблере не загрузить ваше значение?
Загрузить то я могу на асме, НО, суть в том чтобы Си заставить отвести эти регистры чисто для моих переменных, ведь они там все время жизни находятся..... Если Си не заставить этого сделать, то он может их испортить, используя эти регистры по своему усмотрению.....
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Вопросы по С/С++ (СИ)

Сообщение shads »

vitalik_1984 писал(а):А что сама идея быстродействия разбивается о скалы бесполезного счетчика и ненужного сравнения вас не тревожит?
Так я же сказал, что этот код никогда не запустится, ну будет одно сравнение, которое никогда не будет истинным, но это в майне, там мне и не нужно особое быстродействие..... оно нужно именно в прерывании, т.к. 250000Гц это не шуточки.....

vitalik_1984 писал(а):Может тогда так?
PORTB = Div5 = Div250 = TimerL = TimerH= Flags=(тут нужное значение для порта B);
Во первых мне и не нужно это значение, т.к. в порт ничего и не выводится.... во вторых у меня эти переменные инитятся разными значениями, а так как вы предложили, они все проинитятся одним числом.....
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение vitalik_1984 »

shads писал(а):Пробовал инлайнить Сишную процедуру.....

Стоп стоп, сишную процедуру?
Я про инлайн ассемблер. Проходили по ссылке, что я вам дал? Вы ведь сами код пишете на асме, каким образом получится
вместо обычного:
dec r2
вставляет:
mov r24,r2
subi r24,254
?
а так как вы предложили, они все проинитятся одним числом.....

Зато будут живы(наверно) и можно будет их использовать как положено без траты тактов во время работы.

Почитал тут немного еще раз :

asm [volatile] («команды и директивы ассемблера» : выходные параметры : входные параметры : изменяемые параметры);

может нужно еще после asm volatile поставить?
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Вопросы по С/С++ (СИ)

Сообщение shads »

vitalik_1984 писал(а):Я про инлайн ассемблер. Проходили по ссылке, что я вам дал?
По ссылке проходил, честно говоря от инлайнового асма у меня голова кружится....слишком перегружен синтаксис.....
Хотя, можно попробовать и такой вариант. Единственное, вызов прерывания в моем случае полностью подконтролен мне, т.е. с первой команды обработчика я управляю процессом..... а в случае инлайнового обработчика, вызов будет обрабатыватся компилятором, и только после того как он насохраняет кучу регистров в стеке, я смогу получить доступ для инлайновых асмо команд.....

vitalik_1984 писал(а):Вы ведь сами код пишете на асме, каким образом получится вместо обычного: dec r2.......
я там чуть не точно описал..... НО, реально.... компиль инкрементирует переменную - 1) вызовом значения в верхний регистр, 2) отнимая от него число 255, 3) загружая опять на место.....

vitalik_1984 писал(а):Почитал тут немного еще раз:
asm [volatile] («команды и директивы ассемблера» : выходные параметры : входные параметры : изменяемые параметры);
может нужно еще после asm volatile поставить?
Ну это опять же для инлайнового варианта, у себя пробовал по разному ставить, результат тот же.....
Аватара пользователя
Kavka
Мудрый кот
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Re: Вопросы по С/С++ (СИ)

Сообщение Kavka »

shads писал(а):Вот и вопросик, Почему компиль оптимизирует volatile выражение?.....
Компилятор "вычищает" его потому что содержимое его нигде не используется.
Добавьте __attribute__ ((used)) в определение.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Аватара пользователя
Kavka
Мудрый кот
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Re: Вопросы по С/С++ (СИ)

Сообщение Kavka »

vitalik_1984 писал(а):Может тогда так?
PORTB = Div5 = Div250 = TimerL = TimerH= Flags=(тут нужное значение для порта B);
Осторожно. Могут быть грабли http://www.nongnu.org/avr-libc/user-man ... sign_chain
С переменными-то нормально, а вот с портами...
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Re: Вопросы по С/С++ (СИ)

Сообщение ibiza11 »

Kavka писал(а):Осторожно. Могут быть грабли
там же написано про несколько портов (один из которых имеет неполную реализацию в железе), а в примере один порт. Единственное, что грозит в этом случае это "The compiler stands no chance to optimize". В случае поочередного присваивания выполняется меньше инструкции, чем в случае присваивания в одной строке.
Ставим плюсы: )
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Re: Вопросы по С/С++ (СИ)

Сообщение shads »

Kavka писал(а):
shads писал(а):Вот и вопросик, Почему компиль оптимизирует volatile выражение?.....
Компилятор "вычищает" его потому что содержимое его нигде не используется.
Добавьте __attribute__ ((used)) в определение.

Не...... не катит.....

И еще один момент.. по идее в ассемблерном файле я должен видеть сишные переменные, объявляя их напрмер так: .extern Div5
А НЕВИЖУ.....
из за этого вынужден либо напрямую работать с регистрами, либо обзывая регистры повторно в ассм файле...
Ответить

Вернуться в «Разные вопросы по МК»