Нескольно простых вопросов о программировании AVR на Си.
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Нескольно простых вопросов о программировании AVR на Си.
Спасибо !!! Представляю себе, сколько ног еще предстоит отстрелить 
- Реклама
Re: Нескольно простых вопросов о программировании AVR на Си.
[uquote="ARV",url="/forum/viewtopic.php?p=3207842#p3207842"]И еще: из обработчика прерываний крайне нежелательно вызывать другие функции, тем более с параметрами. Но если уж очень хочется, делайте все эти вызываемые из прерывания функции static, и, по возможности, ниоткуда более их не вызывайте.[/uquote]
Это (во многих случаях) вредный совет.
Функции бывают реентерабельные и нереетерабельные. Например, что мешает вызвать memset () из обработчика прерывания, если "заливаемая" область памяти используется только в этом обработчике? Она (функция memset () ) и глобальная, и с параметрами и много откуда вызывается. Что надо функционал memset () в обработчик переносить?
Обработчик прерывания - это фактически еще один "поток" выполнения, который выполняется одновременно с основным потоком (в принципе, одновременно может выполняться много потоков, больше, чем два: основной и обработчик - это сейчас не важно).
Функции могут быть потокобезопасными, а могут и не быть таковыми. Потокобезопасные функции можно вызывать из одновременно выполняющихся потоков, так как потокобезопасные функции упорядочивают доступ к общим данным (если таковые имеются). Соответственно, потокобезопасную функцию можно вызывать из обработчика (пока не рассматриваем функции, которые ждут какого либо события, например, нажатия кнопки пользователем - понятно, что ждать нажания кнопки в обработчике нельзя).
Пока_без_кота, вот тебе еще "грабли" (так на всякий случай
). Про атомарнось. volatile к атомарности не имеет никакого отношения.
Присвоение значения указателю parsing_pointer - это неатомарная операция (прерывание может возникнуть, когда операция начала выполняться, но не завершилась). Как минимум две ассемблерные команды нужно, чтобы сохранить значение 16-ти битного указателя. Если прерывания разрешены и в обработчике используется parsing_pointer, обработчик может быть вызван между сохранением "половинок" указателя parsing_pointer. Такую ошибку найти черезвычайно трудно (может неделями и месяцами не проявляться).
Это (во многих случаях) вредный совет.
Функции бывают реентерабельные и нереетерабельные. Например, что мешает вызвать memset () из обработчика прерывания, если "заливаемая" область памяти используется только в этом обработчике? Она (функция memset () ) и глобальная, и с параметрами и много откуда вызывается. Что надо функционал memset () в обработчик переносить?
Обработчик прерывания - это фактически еще один "поток" выполнения, который выполняется одновременно с основным потоком (в принципе, одновременно может выполняться много потоков, больше, чем два: основной и обработчик - это сейчас не важно).
Функции могут быть потокобезопасными, а могут и не быть таковыми. Потокобезопасные функции можно вызывать из одновременно выполняющихся потоков, так как потокобезопасные функции упорядочивают доступ к общим данным (если таковые имеются). Соответственно, потокобезопасную функцию можно вызывать из обработчика (пока не рассматриваем функции, которые ждут какого либо события, например, нажатия кнопки пользователем - понятно, что ждать нажания кнопки в обработчике нельзя).
Пока_без_кота, вот тебе еще "грабли" (так на всякий случай
Присвоение значения указателю parsing_pointer - это неатомарная операция (прерывание может возникнуть, когда операция начала выполняться, но не завершилась). Как минимум две ассемблерные команды нужно, чтобы сохранить значение 16-ти битного указателя. Если прерывания разрешены и в обработчике используется parsing_pointer, обработчик может быть вызван между сохранением "половинок" указателя parsing_pointer. Такую ошибку найти черезвычайно трудно (может неделями и месяцами не проявляться).
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18546
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Нескольно простых вопросов о программировании AVR на Си.
это в применении к AVR практически всегда безусловно правильный совет. вы как-то совсем упускаете из виду, что главный ресурс AVR, который стоит беречь всеми силами, это ОЗУ. так вот, использование не-static функций в обработчике прерывания приводит к тому, что в стеке сохраняется слишком много регистров, а в случае с вызовом функций из других модулей или библиотечных, будут сохранены в стеке вообще все рабочие регистры.viiv писал(а):Это (во многих случаях) вредный совет.
и кому это надо?
а вот static-функции практически со 100% вероятностью будут проинлайнены и не смотря на количество передаваемых параметров обеспечат наиболее экономную трату стека. Ну и обрабатываться в итоге прерывание будет наиболее быстро.
как я и говорил, моя рекомендация наиболее эффективна, если эти функции более ниоткуда не вызываются. если они используются из нескольких мест, то со стеком не все так красиво...
вообще, совет определять все функции модуля, которые нужны только этому модулю, как static - вообще в практике AVR-программирования однозначно полезный совет.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: Нескольно простых вопросов о программировании AVR на Си.
[uquote="ARV",url="/forum/viewtopic.php?p=3208966#p3208966"]это в применении к AVR практически всегда безусловно правильный совет. вы как-то совсем упускаете из виду, что главный ресурс AVR, который стоит беречь всеми силами, это ОЗУ. так вот, использование не-static функций в обработчике прерывания приводит к тому, что в стеке сохраняется слишком много регистров, а в случае с вызовом функций из других модулей или библиотечных, будут сохранены в стеке вообще все рабочие регистры.
и кому это надо?
а вот static-функции практически со 100% вероятностью будут проинлайнены и не смотря на количество передаваемых параметров обеспечат наиболее экономную трату стека. Ну и обрабатываться в итоге прерывание будет наиболее быстро.
как я и говорил, моя рекомендация наиболее эффективна, если эти функции более ниоткуда не вызываются. если они используются из нескольких мест, то со стеком не все так красиво...[/uquote]
Отчасти Вы правы, но:
I) Ради простоты, понятности, надежности.... исходного кода я с легкостью пойду на некоторые расходы (если надо перейду на MK c бОльшимми ресурсами). Например, вызов функции из стандартной библиотеки вместо static аналога, повышает понятность кода. Если не согласны - спорить не буду, но убедить в обратном меня практически невозможно ("опыт, сын ошибок трудных")
1) Разница в цене минимальна, например atmega48pa/atmega88pa (чип-дип: разница 6руб, для других поставщиков можете сами посмотреть) Если понятность и повторное использование кода, позволяет съекономить хотябы день разработчика, можно прикунуть, какой тираж нужен, чтобы окупить это.
2) более того, с учетом реалий, часто более старшую модель семейства можно купить даже дешевле (как более массовую).
II) Как я писал ранее, для меня важна простота, понятность, надежность, повторное использование исходного кода (минимизация времени программиста на разработку и сопровождение). А голова пусть у оптимизатора болит - у компьютера мегагерцев много. Оптимизатор опровергает Ваши доводы:
Вот во что все это скомпилировалось:
Видно, что:
1) Оптимизатор заинлайнил memset () из стандартной библиотеки
2) Сохранения всех регистров, как Вы говорите, не имеет места быть
Для сравнения, то, что получилось, если раскоментарить my_memset () и вызвать ее вместо memset () из стандартной библиотеки:
Да, использование стека, в случае локального static аналога memset () меньше, но совсем не так, как Вы предсказываете. Если я буду компилировать более свежей версией (сейчас gcc 4.5.3), не уверен, что эта разница вообще не уйдет на нет.
[uquote="ARV",url="/forum/viewtopic.php?p=3208966#p3208966"]вообще, совет определять все функции модуля, которые нужны только этому модулю, как static - вообще в практике AVR-программирования однозначно полезный совет.[/uquote]
С этим вообще спорить бесполезно, так как полностью согласен. Но речь шла совсем про другое.
и кому это надо?
а вот static-функции практически со 100% вероятностью будут проинлайнены и не смотря на количество передаваемых параметров обеспечат наиболее экономную трату стека. Ну и обрабатываться в итоге прерывание будет наиболее быстро.
как я и говорил, моя рекомендация наиболее эффективна, если эти функции более ниоткуда не вызываются. если они используются из нескольких мест, то со стеком не все так красиво...[/uquote]
Отчасти Вы правы, но:
I) Ради простоты, понятности, надежности.... исходного кода я с легкостью пойду на некоторые расходы (если надо перейду на MK c бОльшимми ресурсами). Например, вызов функции из стандартной библиотеки вместо static аналога, повышает понятность кода. Если не согласны - спорить не буду, но убедить в обратном меня практически невозможно ("опыт, сын ошибок трудных")
1) Разница в цене минимальна, например atmega48pa/atmega88pa (чип-дип: разница 6руб, для других поставщиков можете сами посмотреть) Если понятность и повторное использование кода, позволяет съекономить хотябы день разработчика, можно прикунуть, какой тираж нужен, чтобы окупить это.
2) более того, с учетом реалий, часто более старшую модель семейства можно купить даже дешевле (как более массовую).
II) Как я писал ранее, для меня важна простота, понятность, надежность, повторное использование исходного кода (минимизация времени программиста на разработку и сопровождение). А голова пусть у оптимизатора болит - у компьютера мегагерцев много. Оптимизатор опровергает Ваши доводы:
Спойлер
Код: Выделить всё
/*
static void* my_memset (void *b, int c, int s)
{
register char* p = (char*) b;
while (s-- > 0)
*p++ = (char) c;
return b;
}
*/
static char buffer [18];
ISR (INT0_vect)
{
memset (buffer, 0, sizeof (buffer));
}Спойлер
Код: Выделить всё
00000090 <__vector_1>:
90: 1f 92 push r1
92: 0f 92 push r0
94: 0f b6 in r0, 0x3f ; 63
96: 0f 92 push r0
98: 11 24 eor r1, r1
9a: 8f 93 push r24
9c: af 93 push r26
9e: bf 93 push r27
a0: ef 93 push r30
a2: ff 93 push r31
a4: 82 e1 ldi r24, 0x12 ; 18
a6: e0 e0 ldi r30, 0x00 ; 0
a8: f1 e0 ldi r31, 0x01 ; 1
aa: df 01 movw r26, r30
ac: 1d 92 st X+, r1
ae: 8a 95 dec r24
b0: e9 f7 brne .-6 ; 0xac <__vector_1+0x1c>
b2: ff 91 pop r31
b4: ef 91 pop r30
b6: bf 91 pop r27
b8: af 91 pop r26
ba: 8f 91 pop r24
bc: 0f 90 pop r0
be: 0f be out 0x3f, r0 ; 63
c0: 0f 90 pop r0
c2: 1f 90 pop r1
c4: 18 95 reti
000000c6 <main>:
c6: 89 ea ldi r24, 0xA9 ; 169
c8: 90 e0 ldi r25, 0x00 ; 0
ca: 08 95 ret
000000cc <_exit>:
cc: f8 94 cli
000000ce <__stop_program>:
ce: ff cf rjmp .-2 ; 0xce <__stop_program>
1) Оптимизатор заинлайнил memset () из стандартной библиотеки
2) Сохранения всех регистров, как Вы говорите, не имеет места быть
Для сравнения, то, что получилось, если раскоментарить my_memset () и вызвать ее вместо memset () из стандартной библиотеки:
Спойлер
Код: Выделить всё
00000090 <__vector_1>:
90: 1f 92 push r1
92: 0f 92 push r0
94: 0f b6 in r0, 0x3f ; 63
96: 0f 92 push r0
98: 11 24 eor r1, r1
9a: 8f 93 push r24
9c: ef 93 push r30
9e: ff 93 push r31
a0: e0 e0 ldi r30, 0x00 ; 0
a2: f1 e0 ldi r31, 0x01 ; 1
a4: 11 92 st Z+, r1
a6: 81 e0 ldi r24, 0x01 ; 1
a8: e2 31 cpi r30, 0x12 ; 18
aa: f8 07 cpc r31, r24
ac: d9 f7 brne .-10 ; 0xa4 <__vector_1+0x14>
ae: ff 91 pop r31
b0: ef 91 pop r30
b2: 8f 91 pop r24
b4: 0f 90 pop r0
b6: 0f be out 0x3f, r0 ; 63
b8: 0f 90 pop r0
ba: 1f 90 pop r1
bc: 18 95 reti
000000be <main>:
be: 89 ea ldi r24, 0xA9 ; 169
c0: 90 e0 ldi r25, 0x00 ; 0
c2: 08 95 ret
000000c4 <_exit>:
c4: f8 94 cli
000000c6 <__stop_program>:
c6: ff cf rjmp .-2 ; 0xc6 <__stop_program>
[uquote="ARV",url="/forum/viewtopic.php?p=3208966#p3208966"]вообще, совет определять все функции модуля, которые нужны только этому модулю, как static - вообще в практике AVR-программирования однозначно полезный совет.[/uquote]
С этим вообще спорить бесполезно, так как полностью согласен. Но речь шла совсем про другое.
Re: Нескольно простых вопросов о программировании AVR на Си.
PS. Провел лабораторную работу.
Скомпилировал код от Пока_без_кота из этой ветки. Код не правил, добавил только несколько определений, чтобы компилировалось (warning-и не убирал) - файла AVR_caller.h у меня нету
Компилировал два варианта: 1) как есть 2) все функции (кроме main и обработчика - static)
Получил, то, что и ожидал. С включенной глобальной оптимизацией полученные бинарники (размер 324 байта) совпадают байт-в-байт. Без глобальной оптимизации: 1) размер 388 байт, в обработчике упрятывается в стек на 8 байт больше. 2) размер 324байта, бинарник байт-в-байт совпадает с теми, что собраны с глобальной оптимизацией
Вывод: static функции не влияют на оптимальность сгенерированного кода - оптимизатор все "подчистит".
Всем доброго дня.
Скомпилировал код от Пока_без_кота из этой ветки. Код не правил, добавил только несколько определений, чтобы компилировалось (warning-и не убирал) - файла AVR_caller.h у меня нету
Компилировал два варианта: 1) как есть 2) все функции (кроме main и обработчика - static)
Получил, то, что и ожидал. С включенной глобальной оптимизацией полученные бинарники (размер 324 байта) совпадают байт-в-байт. Без глобальной оптимизации: 1) размер 388 байт, в обработчике упрятывается в стек на 8 байт больше. 2) размер 324байта, бинарник байт-в-байт совпадает с теми, что собраны с глобальной оптимизацией
Вывод: static функции не влияют на оптимальность сгенерированного кода - оптимизатор все "подчистит".
Всем доброго дня.
- Реклама
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18546
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Нескольно простых вопросов о программировании AVR на Си.
низачотviiv писал(а):Провел лабораторную работу.
лабораторная работа выглядит так.
В проекте два модуля, их исходники в спойлерах
Спойлер
Код: Выделить всё
#include <avr/io.h>
static uint8_t func_local(uint8_t b){
return (b >> 2) | (b << 2);
}
int main(void){
while(1){
PORTB = func_local(PINB);
PORTB = func_module(PINB);
}
}
Спойлер
Код: Выделить всё
#include <avr/io.h>
static uint8_t func_local2(uint8_t dd){
return dd + (1<<dd);
}
uint8_t func_module(uint8_t d){
return func_local2(d>>2) + (d<<2);
}
теперь удаляем static из обоих модулей, делая все функции публично видимыми (обратите внимание, что во втором модуле пришлось локальной функции цифру приписать, чтобы конфликта имен не было). получаем следующееDevice: atmega8
Program: 118 bytes (1.4% Full)
(.text + .data + .bootloader)
Data: 0 bytes (0.0% Full)
(.data + .bss + .noinit)
оба варианта компилировались в режиме оптимизации -OsDevice: atmega8
Program: 152 bytes (1.9% Full)
(.text + .data + .bootloader)
Data: 0 bytes (0.0% Full)
(.data + .bss + .noinit)
Теперь делаем то же самое, но с компилятором посвежее, а именно 6.3.0
и без staticDevice: atmega8
Program: 118 bytes (1.4% Full)
(.text + .data + .bootloader)
Data: 0 bytes (0.0% Full)
(.data + .bss + .noinit)
а вот теперь делаем вывод, что больше влияет на результат: static или поведение оптимизатораDevice: atmega8
Program: 154 bytes (1.9% Full)
(.text + .data + .bootloader)
Data: 0 bytes (0.0% Full)
(.data + .bss + .noinit)
Добавлено after 8 minutes 20 seconds:
заодно задумываемся о том, что будет, если модулей в проекте 20, и функций в них штук по 20, и параметров в функциях не по одному... но это уже факультативно
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: Нескольно простых вопросов о программировании AVR на Си.
ARV, Вы делаете преждевременные выводы
[uquote="ARV",url="/forum/viewtopic.php?p=3210511#p3210511"]низачот
[/uquote]
Препод из Вас так себе
gcc version 4.5.3 (atmega8)
static
static убран
включаем глобальную опитмизацию:
static
static убран:
Бинарники которые выдал оптимизатор (со static и без) совпадают баит-в-байт (и выиграл целую команду (два байта) у static-a
):
Вот код (выхлоп оптимизатора):
[uquote="ARV",url="/forum/viewtopic.php?p=3210511#p3210511"]заодно задумываемся о том, что будет, если модулей в проекте 20, и функций в них штук по 20, и параметров в функциях не по одному... но это уже факультативно
[/uquote]
Да нормально все там. И поболее проекты есть. Уже много лет пользуюсь. Никогда не делаю static функций только для оптимизации. Исключительно по назначению: чтобы ограничить "видимость". И уж никогда не буду дублировать код, если есть глобальная функция (проверенная и отлаженная), которая делает то, что надо - вызову ее (сообственно для этого она и глобальная - чтобы ее вызывать, когда надо
)
[uquote="ARV",url="/forum/viewtopic.php?p=3210511#p3210511"]низачот
Препод из Вас так себе
gcc version 4.5.3 (atmega8)
static
Код: Выделить всё
text data bss dec hex filename
114 0 0 114 72 ./sta
Код: Выделить всё
text data bss dec hex filename
148 0 0 148 94 ./std
static
Код: Выделить всё
text data bss dec hex filename
112 0 0 112 70 ./sta-lto
Код: Выделить всё
text data bss dec hex filename
112 0 0 112 70 ./std-lto
Бинарники которые выдал оптимизатор (со static и без) совпадают баит-в-байт (и выиграл целую команду (два байта) у static-a
Вот код (выхлоп оптимизатора):
Спойлер
Код: Выделить всё
Disassembly of section .text:
00000000 <__vectors>:
0: 12 c0 rjmp .+36 ; 0x26 <__ctors_end>
2: 19 c0 rjmp .+50 ; 0x36 <__bad_interrupt>
4: 18 c0 rjmp .+48 ; 0x36 <__bad_interrupt>
6: 17 c0 rjmp .+46 ; 0x36 <__bad_interrupt>
8: 16 c0 rjmp .+44 ; 0x36 <__bad_interrupt>
a: 15 c0 rjmp .+42 ; 0x36 <__bad_interrupt>
c: 14 c0 rjmp .+40 ; 0x36 <__bad_interrupt>
e: 13 c0 rjmp .+38 ; 0x36 <__bad_interrupt>
10: 12 c0 rjmp .+36 ; 0x36 <__bad_interrupt>
12: 11 c0 rjmp .+34 ; 0x36 <__bad_interrupt>
14: 10 c0 rjmp .+32 ; 0x36 <__bad_interrupt>
16: 0f c0 rjmp .+30 ; 0x36 <__bad_interrupt>
18: 0e c0 rjmp .+28 ; 0x36 <__bad_interrupt>
1a: 0d c0 rjmp .+26 ; 0x36 <__bad_interrupt>
1c: 0c c0 rjmp .+24 ; 0x36 <__bad_interrupt>
1e: 0b c0 rjmp .+22 ; 0x36 <__bad_interrupt>
20: 0a c0 rjmp .+20 ; 0x36 <__bad_interrupt>
22: 09 c0 rjmp .+18 ; 0x36 <__bad_interrupt>
24: 08 c0 rjmp .+16 ; 0x36 <__bad_interrupt>
00000026 <__ctors_end>:
26: 11 24 eor r1, r1
28: 1f be out 0x3f, r1 ; 63
2a: cf e5 ldi r28, 0x5F ; 95
2c: d4 e0 ldi r29, 0x04 ; 4
2e: de bf out 0x3e, r29 ; 62
30: cd bf out 0x3d, r28 ; 61
32: 09 d0 rcall .+18 ; 0x46 <main>
34: 2d c0 rjmp .+90 ; 0x90 <_exit>
00000036 <__bad_interrupt>:
36: e4 cf rjmp .-56 ; 0x0 <__vectors>
00000038 <func_local>:
38: 98 2f mov r25, r24
3a: 99 0f add r25, r25
3c: 99 0f add r25, r25
3e: 86 95 lsr r24
40: 86 95 lsr r24
42: 89 2b or r24, r25
44: 08 95 ret
00000046 <main>:
46: 96 b3 in r25, 0x16 ; 22
48: 89 2f mov r24, r25
4a: 88 0f add r24, r24
4c: 88 0f add r24, r24
4e: 96 95 lsr r25
50: 96 95 lsr r25
52: 89 2b or r24, r25
54: 88 bb out 0x18, r24 ; 24
56: 86 b3 in r24, 0x16 ; 22
58: 0c d0 rcall .+24 ; 0x72 <func_module>
5a: 88 bb out 0x18, r24 ; 24
5c: f4 cf rjmp .-24 ; 0x46 <main>
0000005e <func_local2>:
5e: 21 e0 ldi r18, 0x01 ; 1
60: 30 e0 ldi r19, 0x00 ; 0
62: 08 2e mov r0, r24
64: 02 c0 rjmp .+4 ; 0x6a <func_local2+0xc>
66: 22 0f add r18, r18
68: 33 1f adc r19, r19
6a: 0a 94 dec r0
6c: e2 f7 brpl .-8 ; 0x66 <func_local2+0x8>
6e: 82 0f add r24, r18
70: 08 95 ret
00000072 <func_module>:
72: 98 2f mov r25, r24
74: 96 95 lsr r25
76: 96 95 lsr r25
78: 88 0f add r24, r24
7a: 88 0f add r24, r24
7c: 89 0f add r24, r25
7e: 21 e0 ldi r18, 0x01 ; 1
80: 30 e0 ldi r19, 0x00 ; 0
82: 02 c0 rjmp .+4 ; 0x88 <func_module+0x16>
84: 22 0f add r18, r18
86: 33 1f adc r19, r19
88: 9a 95 dec r25
8a: e2 f7 brpl .-8 ; 0x84 <func_module+0x12>
8c: 82 0f add r24, r18
8e: 08 95 ret
00000090 <_exit>:
90: f8 94 cli
00000092 <__stop_program>:
92: ff cf rjmp .-2 ; 0x92 <__stop_program>
Да нормально все там. И поболее проекты есть. Уже много лет пользуюсь. Никогда не делаю static функций только для оптимизации. Исключительно по назначению: чтобы ограничить "видимость". И уж никогда не буду дублировать код, если есть глобальная функция (проверенная и отлаженная), которая делает то, что надо - вызову ее (сообственно для этого она и глобальная - чтобы ее вызывать, когда надо
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18546
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Нескольно простых вопросов о программировании AVR на Си.
Что такое "глобальная оптимизация"? я такого в упор не знаю...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: Нескольно простых вопросов о программировании AVR на Си.
[uquote="ARV",url="/forum/viewtopic.php?p=3210621#p3210621"]Что такое "глобальная оптимизация"? я такого в упор не знаю...[/uquote]
хм... я думал, это всем, кто более-менее gcc пользует известно
Введено в районе версии 4.5 - сейчас точно не помню. Но в 4.5.3 точно есть. смотреть ключики -combine -fwhole-program
В районе 4.6 версии (точно сейчас не помню - гуглить надо, да и неважно это), gcc-шники модернизировали эту "фичу", теперь она называется LTO (link time optimization) - принцип работы понятен из названия (оптимизация на этапе линковки, т.е. всего кода целиком).
хм... я думал, это всем, кто более-менее gcc пользует известно
Введено в районе версии 4.5 - сейчас точно не помню. Но в 4.5.3 точно есть. смотреть ключики -combine -fwhole-program
В районе 4.6 версии (точно сейчас не помню - гуглить надо, да и неважно это), gcc-шники модернизировали эту "фичу", теперь она называется LTO (link time optimization) - принцип работы понятен из названия (оптимизация на этапе линковки, т.е. всего кода целиком).
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18546
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Нескольно простых вопросов о программировании AVR на Си.
вот именно - прочтите условия эксперимента, которые я описал.viiv писал(а):Введено в районе версии 4.5
LTO более-менее задышала совсем недавно (ну... как сказать, время летит...), и пока что лично я к этому еще не привык. А -combine -fwhole-program работает только в случае специально вручную созданного makefile или из командной строки, а я работаю из-под Eclipse, который компилирует файлы поотдельности и эту опцию не дает применять. И я уверен, что практически все тут собравшиеся поступают аналогично - все автоматом... так что, не смотря на то, что LTO и в самом деле дает какой-то эффект, лично я его никак не прочувствовал. но посмотрите: я получил ровно тот же результат без этой фичи, т.е. мой совет подходит для всех, а ваш - для приближающихся к просветлению...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: Нескольно простых вопросов о программировании AVR на Си.
ARV, как поступают все (или большинство) - мне неведомо, да и незачем мне это.
Сделать нужный Makefile: не считаю это "просветлением", обычное дело. Да и какой там Makefile - мэйкфайлик, ситаю всем кто собирает проекты - хотябы основы make знать надо. Намного жизнь облегчает.
[uquote="ARV",url="/forum/viewtopic.php?p=3210653#p3210653"]вот именно - прочтите условия эксперимента, которые я описал.[/uquote]
прочитал. 6.3.0 не умеет lto? Или опция в Eclipse не вбивается?
Никому ничего не навязываю
Как говорится, "думайте сами решайте сами..."
Сделать нужный Makefile: не считаю это "просветлением", обычное дело. Да и какой там Makefile - мэйкфайлик, ситаю всем кто собирает проекты - хотябы основы make знать надо. Намного жизнь облегчает.
[uquote="ARV",url="/forum/viewtopic.php?p=3210653#p3210653"]вот именно - прочтите условия эксперимента, которые я описал.[/uquote]
прочитал. 6.3.0 не умеет lto? Или опция в Eclipse не вбивается?
Никому ничего не навязываю
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Нескольно простых вопросов о программировании AVR на Си.
Пока_без_кота, в чем вопрос? В том, что в соответствующем файле 7-ой бит регистра не определён?
Он, вроде, SPI режим включает, если правильно помню.
Так определите , если Вам нужно
Он, вроде, SPI режим включает, если правильно помню.
Так определите , если Вам нужно
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Нескольно простых вопросов о программировании AVR на Си.
Ну то что 7 бита нет, это одно, так еще и 6 бит не так называеться... По Вашей спокойной реакции, я так понимаю, такие плюхи сплошь и рядом, и на никто даже внимания не обращает ?
Просто я компилирую, оно материться, я лезу в даташит, 10 раз перепроверяю, ишу ревизии даташита посвежее, убеждаюсь, что у меня самая последняя ревизия, читаю ерраты, ничего не нахожу, потом заглядываю в определения студии и офигеваю... Они просто взяли определения этого регистра от Тини2313 без А, а там иначе.
Просто я компилирую, оно материться, я лезу в даташит, 10 раз перепроверяю, ишу ревизии даташита посвежее, убеждаюсь, что у меня самая последняя ревизия, читаю ерраты, ничего не нахожу, потом заглядываю в определения студии и офигеваю... Они просто взяли определения этого регистра от Тини2313 без А, а там иначе.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18546
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: Нескольно простых вопросов о программировании AVR на Си.
Лично я сочувствую тем, кто USI в реализации attny2313 использует. И, поверьте, некорректное описание его битов - это мелкие неприятности...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: Нескольно простых вопросов о программировании AVR на Си.
[uquote="Пока_без_кота",url="/forum/viewtopic.php?p=3212498#p3212498"]Ну то что 7 бита нет, это одно, так еще и 6 бит не так называеться... По Вашей спокойной реакции, я так понимаю, такие плюхи сплошь и рядом, и на никто даже внимания не обращает ?
Просто я компилирую, оно материться, я лезу в даташит, 10 раз перепроверяю, ишу ревизии даташита посвежее, убеждаюсь, что у меня самая последняя ревизия, читаю ерраты, ничего не нахожу, потом заглядываю в определения студии и офигеваю... Они просто взяли определения этого регистра от Тини2313 без А, а там иначе.[/uquote]
А Вы думаете, avr libc боги пишут? беглый просмотр различий 2323a и 2323 показывает, что если откопировать iotn2313.h в iotn2313a.h (и поправить io.h), то исходник написанный для 2313 можно откомпилировать для 2313a и он будет работать в 2313А. Все - большинство пользователей удовлетворено. А некоторые различия потои можно поправить
ЗЫ В AVR C Runtime Library 2.0.0 поправлено:
Просто я компилирую, оно материться, я лезу в даташит, 10 раз перепроверяю, ишу ревизии даташита посвежее, убеждаюсь, что у меня самая последняя ревизия, читаю ерраты, ничего не нахожу, потом заглядываю в определения студии и офигеваю... Они просто взяли определения этого регистра от Тини2313 без А, а там иначе.[/uquote]
А Вы думаете, avr libc боги пишут? беглый просмотр различий 2323a и 2323 показывает, что если откопировать iotn2313.h в iotn2313a.h (и поправить io.h), то исходник написанный для 2313 можно откомпилировать для 2313a и он будет работать в 2313А. Все - большинство пользователей удовлетворено. А некоторые различия потои можно поправить
ЗЫ В AVR C Runtime Library 2.0.0 поправлено:
Спойлер
Код: Выделить всё
#define UCSRC _SFR_IO8(0x003)
#define UCPOL 0
#define UCSZ0 1
#define UCSZ1 2
#define USBS 3
#define UPM0 4
#define UPM1 5
#define UMSEL0 6
#define UMSEL1 7
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Нескольно простых вопросов о программировании AVR на Си.
Ну во всяком случае приближенные к ним. Понял, теперь все время буду начеку.
Возник еще вопрос. Для того, чтобы отправить SMS, надо отправить в модуль SIMCOM строку вида AT+CMGS="номер_телефона". Проблема в том, что компилятор ограничивает строки как раз такими же кавычками. Как это побороть ?
Возник еще вопрос. Для того, чтобы отправить SMS, надо отправить в модуль SIMCOM строку вида AT+CMGS="номер_телефона". Проблема в том, что компилятор ограничивает строки как раз такими же кавычками. Как это побороть ?
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Нескольно простых вопросов о программировании AVR на Си.
"AT+CMGS=\"номер_телефона\""
https://www.yandex.ru/yandsearch?clid=9 ... 08659087.1
https://www.yandex.ru/yandsearch?clid=9 ... 08659087.1
-
Пока_без_кота
- Потрогал лапой паяльник
- Сообщения: 359
- Зарегистрирован: Чт авг 08, 2013 01:06:54
Re: Нескольно простых вопросов о программировании AVR на Си.
Благодарю. На этот раз мне все понятно сразу 
-
sibiryak69
- Первый раз сказал Мяу!
- Сообщения: 24
- Зарегистрирован: Вс июн 19, 2016 06:31:18
Re: Нескольно простых вопросов о программировании AVR на Си.
Всем добрый день. Подскажите кто знает.
В книге белова в описании последовательного интерфейса USART есть такой пример инициализации
Пример на языке СИ (Code Vision)
#define RXEN 4
#define TXEN 3
#define USBS 3
#define UCSZO 1
void USART_Init( unsigned int baud )
{
/* Установка скорости передачи */
UBRPH = (unsigned char)(baud>>8);
UBRRL = (unsigned char)baud;
/* Включение приемника и передатчика */
UCSRB = (1<<RXEN) | (1<<TXEN);
/* Установка формата кадра: 8 бит данных, 2 стоповых бита */
UCSRC = (1<<USBS) |(3<<UCSZ0);
}
в данном примере не совсем понятны две строки
UBRPH = (unsigned char)(baud>>8);
UBRRL = (unsigned char)baud;
а точнее не совсем понятно зачем unsigned char заключено в круглые скобки
В книге белова в описании последовательного интерфейса USART есть такой пример инициализации
Пример на языке СИ (Code Vision)
#define RXEN 4
#define TXEN 3
#define USBS 3
#define UCSZO 1
void USART_Init( unsigned int baud )
{
/* Установка скорости передачи */
UBRPH = (unsigned char)(baud>>8);
UBRRL = (unsigned char)baud;
/* Включение приемника и передатчика */
UCSRB = (1<<RXEN) | (1<<TXEN);
/* Установка формата кадра: 8 бит данных, 2 стоповых бита */
UCSRC = (1<<USBS) |(3<<UCSZ0);
}
в данном примере не совсем понятны две строки
UBRPH = (unsigned char)(baud>>8);
UBRRL = (unsigned char)baud;
а точнее не совсем понятно зачем unsigned char заключено в круглые скобки


