Страница 3 из 4
Re: arduino и конденсатор
Добавлено: Вт окт 22, 2019 14:02:51
oleg_4rk
Точно. Про else забыл. Но подобный макрос изврат в любом случае. Лучше уж inline:
Код: Выделить всё
static inline void lighton(void)
{
PORTB |= (1 << PB3);
DDRB |= (1 << DDRB3);
}
Re: arduino и конденсатор
Добавлено: Вт окт 22, 2019 14:13:18
NStorm
Макрос - не изврат, а вполне себе стандартная практика. А inline - не панацея. Это всего-лишь хинт компилятору. Не факт, что будет инлайн. Ладно еще с avr-gcc, на другой платформе, например PIC с XC8 там вообще всё плохо с этим.
Плюс макрос можно закинуть в .h и вызывать из разных .c.
Re: arduino и конденсатор
Добавлено: Вт окт 22, 2019 14:32:49
oleg_4rk
[uquote="NStorm",url="/forum/viewtopic.php?p=3722831#p3722831"]Макрос - не изврат, а вполне себе стандартная практика.[/uquote]
Макрос норм, но подобный макрос изврат ещё тот.
А inline - не панацея. Это всего-лишь хинт компилятору. Не факт, что будет инлайн.
Если не использовать опции оптимизации, то точно не будет. А если делать -Os - что для avr-gcc strongly recommended - то всё норм.
Или использовать __attribute__((always_inline)).
Ладно еще с avr-gcc, на другой платформе, например PIC с XC8 там вообще всё плохо с этим.
Ну, это прискорбно. Но это не значит, что на нормальных платформах теперь тоже стоит себя ограничивать в удобных инструментах

.
Плюс макрос можно закинуть в .h и вызывать из разных .c.
Так и static inline тоже - никаких проблем. Так и используют. Вот, хотя бы, list.h -
https://github.com/torvalds/linux/blob/ ... nux/list.h .
Добавлено after 2 minutes:
[uquote="NStorm",url="/forum/viewtopic.php?p=3722831#p3722831"]Макрос - не изврат, а вполне себе стандартная практика.[/uquote]
И, кстати, одно другому не противоречит

. Это не перестаёт быть извратом от того, что его часто используют.
Re: arduino и конденсатор
Добавлено: Вт окт 22, 2019 15:32:44
NStorm
__attribute__((always_inline)).
Есть только в gcc. Страдает переносимость кода. Хотя если она не нужна, можно и inline конечно. Если точно уверены в своём компиляторе. Ядру Linux-то пофиг на накладные расходы, если они возникнут. А для МК это критично.
Но для записи битика в пару регистров честно не вижу смысла городить функцию. Диод ставить куда больший изврат )))
PS: Там еще могут быть нюансы при вызове из прерывания.
Добавлено after 14 minutes 20 seconds:
А если делать -Os - что для avr-gcc strongly recommended - то всё норм.
А вот как раз таки наоборот. При -Os делается rcall:
Код: Выделить всё
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/cpufunc.h>
#include <stdbool.h>
static inline void lighton(void) {
PORTB |= (1 << PB3);
DDRB |= (1 << PB3);
}
static inline void lightoff(void) {
PORTB &= ~(1 << PB3);
DDRB &= ~(1 << PB3);
}
ISR(INT0_vect) {
lighton();
}
int main() {
lightoff();
_NOP();
lighton();
while(true);
}
avr-gcc -std=gnu11 -Os -g -mmcu=atmega8 inline.c -o inline && avr-objdump -d inline > inline.lss
inline.lss:
Код: Выделить всё
...
00000038 <lighton>:
38: c3 9a sbi 0x18, 3 ; 24
3a: bb 9a sbi 0x17, 3 ; 23
3c: 08 95 ret
0000003e <__vector_1>:
3e: 1f 92 push r1
40: 0f 92 push r0
42: 0f b6 in r0, 0x3f ; 63
44: 0f 92 push r0
46: 11 24 eor r1, r1
48: 2f 93 push r18
4a: 3f 93 push r19
4c: 4f 93 push r20
4e: 5f 93 push r21
50: 6f 93 push r22
52: 7f 93 push r23
54: 8f 93 push r24
56: 9f 93 push r25
58: af 93 push r26
5a: bf 93 push r27
5c: ef 93 push r30
5e: ff 93 push r31
60: eb df rcall .-42 ; 0x38 <lighton>
62: ff 91 pop r31
64: ef 91 pop r30
66: bf 91 pop r27
68: af 91 pop r26
6a: 9f 91 pop r25
6c: 8f 91 pop r24
6e: 7f 91 pop r23
70: 6f 91 pop r22
72: 5f 91 pop r21
74: 4f 91 pop r20
76: 3f 91 pop r19
78: 2f 91 pop r18
7a: 0f 90 pop r0
7c: 0f be out 0x3f, r0 ; 63
7e: 0f 90 pop r0
80: 1f 90 pop r1
82: 18 95 reti
00000084 <main>:
84: c3 98 cbi 0x18, 3 ; 24
86: bb 98 cbi 0x17, 3 ; 23
88: 00 00 nop
8a: d6 df rcall .-84 ; 0x38 <lighton>
8c: ff cf rjmp .-2 ; 0x8c <main+0x8>
...
Забавно, но такой простой пример выдает с -Os код больше, чем с -Og/-O1 из-за всех этих телодвижений со стеком. -O1 действительно делает инлайн:
Код: Выделить всё
00000044 <__vector_1>:
44: 1f 92 push r1
46: 0f 92 push r0
48: 0f b6 in r0, 0x3f ; 63
4a: 0f 92 push r0
4c: 11 24 eor r1, r1
4e: c3 9a sbi 0x18, 3 ; 24
50: bb 9a sbi 0x17, 3 ; 23
52: 0f 90 pop r0
54: 0f be out 0x3f, r0 ; 63
56: 0f 90 pop r0
58: 1f 90 pop r1
5a: 18 95 reti
Re: arduino и конденсатор
Добавлено: Вт окт 22, 2019 16:43:35
oleg_4rk
[uquote="NStorm",url="/forum/viewtopic.php?p=3722868#p3722868"]
__attribute__((always_inline)).
Есть только в gcc. Страдает переносимость кода. Хотя если она не нужна, можно и inline конечно. Если точно уверены в своём компиляторе. Ядру Linux-то пофиг на накладные расходы, если они возникнут. А для МК это критично.[/uquote]
Я вас умоляю. Если для проекта вызов функции критичен, то надо либо в сторону ассемблера смотреть, либо в сторону контроллера помощнее. Какой смысл жертвовать читаемостью кода, отдавая предпочтение разным хакам.
Но для записи битика в пару регистров честно не вижу смысла городить функцию.
Если это делается двумя выражениями, как выше, плюс do/while(0), то уж лучше функция. Хотя, это субъективно. Каждый сам определяет, когда нужно остановиться

.
Диод ставить куда больший изврат )))
Для обучения норм

.
А если делать -Os - что для avr-gcc strongly recommended - то всё норм.
А вот как раз таки наоборот. При -Os делается rcall:
rcall делается с ISR. Если эту конструкцию убрать, то с inline всё норм.
Re: arduino и конденсатор
Добавлено: Вт окт 22, 2019 18:09:06
NStorm
do { ... } while(0) макро из моего примера подставляется в 2 инструкции asm sbi/cbi. Всегда и везде. Даже с отключенной оптимизацией сами do {} while(0) ни во что не собираются и не дают накладных расходов. Это просто что-то противоположное синтаксическому сахару.
А rcall делается, в случае с функций, что из main(), что из ISR. Вы соберите мой пример сами. С -Os он у меня вроде 146 байт занимал. С -O1 уже 96 байт. Вот и оптимизация по размеру ) А всё из-за тонны вызовов push/pop для сохранения регистров. А вовсе не из-за rcall конечно же.
Если для проекта вызов функции критичен, то надо либо в сторону ассемблера смотреть, либо в сторону контроллера помощнее.
Мне как-то несколько байт не хватало ) Пришлось пожертвовать читаемостью кода и все функции запихнуть одной простыней. Зато влезло в текущий МК, который был под рукой и который не надо было покупать. Это когда речь о личных поделках.
А в серийных ус-ах порой разница в цене за счет серийности может встать в существенную сумму. Всякое бывает.
Хотя, это субъективно. Каждый сам определяет, когда нужно остановиться

.
Именно. На самом деле не критично в большинстве случаев. Мне просто максос с do {} while(0) никак читаемость кода не ухудшает, я к ним привык, они много кем используются. Но случаи бывают разные. )
Re: arduino и конденсатор
Добавлено: Ср окт 23, 2019 12:12:35
oleg_4rk
[uquote="NStorm",url="/forum/viewtopic.php?p=3722975#p3722975"]А rcall делается, в случае с функций, что из main(), что из ISR.[/uquote]
Вы меня не так поняли. Если убрать это из кода:
То вызовов функции не будет в main. Она будет инлайниться. Если эту часть кода оставить, то везде будет вызов lighton и только lightoff будет инлайниться. Видимо, действительно, прерывания вносят что-то своё тут.
Мне как-то несколько байт не хватало ) Пришлось пожертвовать читаемостью кода и все функции запихнуть одной простыней. Зато влезло в текущий МК, который был под рукой и который не надо было покупать. Это когда речь о личных поделках.
Прикольно

.
А в серийных ус-ах порой разница в цене за счет серийности может встать в существенную сумму. Всякое бывает.
Ну, смотря какое серийное производство. Если это промышленное оборудование какое-то, то цена контроллера потеряется среди прочего оборудования, которое он будет мониторить/управлять. И в этом случае для стабильности и надёжности лучше выбрать что-то помощнее и с большей памятью, что бы не извращаться с исходным кодом, ибо больше хаков - больше потенциальных ошибок.
Re: arduino и конденсатор
Добавлено: Ср окт 23, 2019 14:21:44
NStorm
То вызовов функции не будет в main. Она будет инлайниться.
Не хочет )
inline.c:
Код: Выделить всё
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/cpufunc.h>
#include <stdbool.h>
static inline void lighton(void) {
PORTB |= (1 << PB3);
DDRB |= (1 << PB3);
}
static inline void lightoff(void) {
PORTB &= ~(1 << PB3);
DDRB &= ~(1 << PB3);
}
void fn() {
lighton();
}
int main() {
fn();
_NOP();
lightoff();
_NOP();
lighton();
while(true);
}
Выхлоп -Os:
Код: Выделить всё
...
00000038 <lighton>:
38: c3 9a sbi 0x18, 3 ; 24
3a: bb 9a sbi 0x17, 3 ; 23
3c: 08 95 ret
0000003e <fn>:
3e: fc cf rjmp .-8 ; 0x38 <lighton>
00000040 <main>:
40: fb df rcall .-10 ; 0x38 <lighton>
42: 00 00 nop
44: c3 98 cbi 0x18, 3 ; 24
46: bb 98 cbi 0x17, 3 ; 23
48: 00 00 nop
4a: f6 df rcall .-20 ; 0x38 <lighton>
4c: ff cf rjmp .-2 ; 0x4c <main+0xc>
...
А с макросом, что из ISR, что из обычных функций rcall/rjmp не будет )
Re: arduino и конденсатор
Добавлено: Ср окт 23, 2019 14:24:38
BOB51
Ужжшшш выбирайте Си или ассемблер.
Надо хоть под каким-нибудь для начала более-менее разобраться.

Re: arduino и конденсатор
Добавлено: Ср окт 23, 2019 15:34:21
oleg_4rk
[uquote="NStorm",url="/forum/viewtopic.php?p=3723408#p3723408"]
То вызовов функции не будет в main. Она будет инлайниться.
Не хочет )[/uquote]
Да. Точно. Не подумал проверить вызов внутри функции. В этом случае только __attribute__((always_inline)) помогает.
Re: arduino и конденсатор
Добавлено: Ср окт 23, 2019 18:05:49
Dimon456
NStorm, а вы уверены что static inline void у вас действительно inline ,
у меня к примеру что static inline void что static void - одно и то же.
А вот если так указать static inline __attribute__((__always_inline__)) void , то уже совсем другое.
И наиболее оптимальная схема
Спойлер

Если R1 сделать равным R2 300 кОм будет и плавное включение.
Re: arduino и конденсатор
Добавлено: Ср окт 23, 2019 19:35:27
NStorm
Dimon456, я не знаю о чем вы. Я написал, что я уверен, что static inline в определенных случаях становитсяы по факту вовсе не inline, а обычной функцией. И это нормальное поведение в соответствии со стандартом. А __attribute__((__always_inline__)) это нестандартное расширение gcc, о чем я тоже писал уже.
Re: arduino и конденсатор
Добавлено: Чт окт 24, 2019 06:08:06
Dimon456
NStorm, приведите пример.
Re: arduino и конденсатор
Добавлено: Чт окт 24, 2019 07:11:58
Eddy_Em
Dimon456, я несколько раз проверял: gcc при нормальной оптимизации (-O2) static inline обычно раскрывает и подставляет куда нужно. А вот при -Os он оформляет ее как функцию, тратя уйму ресурсов на работу со стеком… Выше уже было про это: в некоторых случаях static inline при -Os приводят к увеличению объема кода…
Вот с sdcc похуже: этот гад творит что хочет!
Re: arduino и конденсатор
Добавлено: Чт окт 24, 2019 08:20:09
NStorm
Dimon456, а выше что? Прочитайте тему целиком пожалуйста, все примеры приведены, всё раскрыто и расписано.
Добавлено after 4 minutes 27 seconds:
Eddy_Em, так и есть, я о том же. Соб-но выше даже показал выхлоп ассемблерный с разными опциями оптимизации на примерах. Но какие-то еще примеры просят )
Re: arduino и конденсатор
Добавлено: Чт окт 24, 2019 14:19:56
Dimon456
Давайте я тогда свой пример приведу
Спойлер
Следующий код-1 Код: Выделить всё
static inline void lighton(void) {
PORTB |= (1 << PB3);
DDRB |= (1 << PB3);
}
static inline void lightoff(void) {
PORTB &= ~(1 << PB3);
DDRB &= ~(1 << PB3);
}
void fn(void) {
lighton();
}
ISR(INT0_vect) {
lighton();
}
int main(void) {
fn();
_NOP();
lightoff();
_NOP();
lighton();
while(true);
}
компилируется в 232 байта. -Os
На выходе имеем Код: Выделить всё
00000080 <lighton>:
80: 2b 9a sbi 0x05, 3 ; 5
82: 23 9a sbi 0x04, 3 ; 4
84: 08 95 ret
00000086 <fn>:
86: 0c 94 40 00 jmp 0x80 ; 0x80 <lighton>
0000008a <__vector_1>:
8a: 1f 92 push r1
8c: 0f 92 push r0
8e: 0f b6 in r0, 0x3f ; 63
90: 0f 92 push r0
92: 11 24 eor r1, r1
94: 2f 93 push r18
96: 3f 93 push r19
98: 4f 93 push r20
9a: 5f 93 push r21
9c: 6f 93 push r22
9e: 7f 93 push r23
a0: 8f 93 push r24
a2: 9f 93 push r25
a4: af 93 push r26
a6: bf 93 push r27
a8: ef 93 push r30
aa: ff 93 push r31
ac: 0e 94 40 00 call 0x80 ; 0x80 <lighton>
b0: ff 91 pop r31
b2: ef 91 pop r30
b4: bf 91 pop r27
b6: af 91 pop r26
b8: 9f 91 pop r25
ba: 8f 91 pop r24
bc: 7f 91 pop r23
be: 6f 91 pop r22
c0: 5f 91 pop r21
c2: 4f 91 pop r20
c4: 3f 91 pop r19
c6: 2f 91 pop r18
c8: 0f 90 pop r0
ca: 0f be out 0x3f, r0 ; 63
cc: 0f 90 pop r0
ce: 1f 90 pop r1
d0: 18 95 reti
000000d2 <main>:
d2: 0e 94 40 00 call 0x80 ; 0x80 <lighton>
d6: 00 00 nop
d8: 2b 98 cbi 0x05, 3 ; 5
da: 23 98 cbi 0x04, 3 ; 4
dc: 00 00 nop
de: 0e 94 40 00 call 0x80 ; 0x80 <lighton>
e2: ff cf rjmp .-2 ; 0xe2 <main+0x10>
Теперь так, код-2Код: Выделить всё
static void lighton(void) {
PORTB |= (1 << PB3);
DDRB |= (1 << PB3);
}
static void lightoff(void) {
PORTB &= ~(1 << PB3);
DDRB &= ~(1 << PB3);
}
void fn(void) {
lighton();
}
ISR(INT0_vect) {
lighton();
}
int main(void) {
fn();
_NOP();
lightoff();
_NOP();
lighton();
while(true);
}
По прежнему 232 байта. -Os
На выходе Код: Выделить всё
00000080 <lighton>:
80: 2b 9a sbi 0x05, 3 ; 5
82: 23 9a sbi 0x04, 3 ; 4
84: 08 95 ret
00000086 <fn>:
86: 0c 94 40 00 jmp 0x80 ; 0x80 <lighton>
0000008a <__vector_1>:
8a: 1f 92 push r1
8c: 0f 92 push r0
8e: 0f b6 in r0, 0x3f ; 63
90: 0f 92 push r0
92: 11 24 eor r1, r1
94: 2f 93 push r18
96: 3f 93 push r19
98: 4f 93 push r20
9a: 5f 93 push r21
9c: 6f 93 push r22
9e: 7f 93 push r23
a0: 8f 93 push r24
a2: 9f 93 push r25
a4: af 93 push r26
a6: bf 93 push r27
a8: ef 93 push r30
aa: ff 93 push r31
ac: 0e 94 40 00 call 0x80 ; 0x80 <lighton>
b0: ff 91 pop r31
b2: ef 91 pop r30
b4: bf 91 pop r27
b6: af 91 pop r26
b8: 9f 91 pop r25
ba: 8f 91 pop r24
bc: 7f 91 pop r23
be: 6f 91 pop r22
c0: 5f 91 pop r21
c2: 4f 91 pop r20
c4: 3f 91 pop r19
c6: 2f 91 pop r18
c8: 0f 90 pop r0
ca: 0f be out 0x3f, r0 ; 63
cc: 0f 90 pop r0
ce: 1f 90 pop r1
d0: 18 95 reti
000000d2 <main>:
d2: 0e 94 40 00 call 0x80 ; 0x80 <lighton>
d6: 00 00 nop
d8: 2b 98 cbi 0x05, 3 ; 5
da: 23 98 cbi 0x04, 3 ; 4
dc: 00 00 nop
de: 0e 94 40 00 call 0x80 ; 0x80 <lighton>
e2: ff cf rjmp .-2 ; 0xe2 <main+0x10>
Теперь такой код-3 Код: Выделить всё
#define INLINE static inline __attribute__((__always_inline__))
INLINE void lighton(void) {
PORTB |= (1 << PB3);
DDRB |= (1 << PB3);
}
INLINE void lightoff(void) {
PORTB &= ~(1 << PB3);
DDRB &= ~(1 << PB3);
}
void fn(void) {
lighton();
}
ISR(INT0_vect) {
lighton();
}
int main(void) {
fn();
_NOP();
lightoff();
_NOP();
lighton();
while(true);
}
компилируется уже в 162 байта. -Os
и на выходе Код: Выделить всё
00000080 <fn>:
80: 2b 9a sbi 0x05, 3 ; 5
82: 23 9a sbi 0x04, 3 ; 4
84: 08 95 ret
00000086 <__vector_1>:
86: 2b 9a sbi 0x05, 3 ; 5
88: 23 9a sbi 0x04, 3 ; 4
8a: 18 95 reti
0000008c <main>:
8c: 0e 94 40 00 call 0x80 ; 0x80 <fn>
90: 00 00 nop
92: 2b 98 cbi 0x05, 3 ; 5
94: 23 98 cbi 0x04, 3 ; 4
96: 00 00 nop
98: 2b 9a sbi 0x05, 3 ; 5
9a: 23 9a sbi 0x04, 3 ; 4
9c: ff cf rjmp .-2 ; 0x9c <main+0x10>
Не хотите в void fn(void) добавить INLINE void fn(void)?
Re: arduino и конденсатор
Добавлено: Чт окт 24, 2019 14:54:43
oleg_4rk
Dimon456, вы не так поняли

. Насчёт того, что __attribute__((always_inline)) работает никто не сомневается. Разговор был про то, что inline не всегда работает. И в этом, в принципе, тоже никто не сомневается. А изначально разговор был о равнозначной по функциональности замене define функцией с inline. Вывод такой, что кому надо не только gcc, то лучше define.
Добавлено after 1 minute 58 seconds:
[uquote="Dimon456",url="/forum/viewtopic.php?p=3723560#p3723560"]И наиболее оптимальная схема

[/uquote]
Я ж правильно понимаю, что R2 можно безболезненно убрать в случае, когда pin переключается с 1 на 0(без HiZ)? Т.е. его единственная задача убирать наводки с базы в случае, когда на пине HiZ, так?
Re: arduino и конденсатор
Добавлено: Чт окт 24, 2019 16:42:51
Dimon456
R2 служит для разрядки конденсатора С1 пока транзистор не закроется.
Два варианта схемы с HiZ.
1- R1=2кОм R2 300кОм, моментальное включение, плавное погасание.
2- R1=300кОм R2 300кОм, плавное включение, плавное погасание.
Один варианта схемы без HiZ.
R1=300кОм R2 убрать, плавное включение, плавное погасание (разряд конденсатора через пин порта).
Re: arduino и конденсатор
Добавлено: Чт окт 24, 2019 19:20:07
oleg_4rk
[uquote="Dimon456",url="/forum/viewtopic.php?p=3724117#p3724117"]Один варианта схемы без HiZ.
R1=300кОм R2 убрать, плавное включение, плавное погасание (разряд конденсатора через пин порта).[/uquote]
Если конденсатор разряжается через пин, а не через транзистор, то никакого плавного погасания нет. Если же добавить слева R1 диод, то всё норм.
Хотя, нет. Наверное будет с 300 КОм. У меня нет таких больших, я с 10 КОм проверял.
Re: arduino и конденсатор
Добавлено: Вс окт 27, 2019 08:49:09
GoldenAndy
По "оптимальной схеме"
Господа, откуда тут будет плавное зажигание-угасание?
Конденсатор через R1 заряжается до момента открывания транзистора, потом будет короткий период действительно плавного открывания транзистора, но потом напряжение на конденсаторе останется равным напряжению падения на открытом переходе база-эммитер.....
Т.е. условно, конденсатор заряжается до 0.55 вольта через резистор, потом начинает открываться транзистор и... всё.... при 0.65-0.7 вольта заряд ёмкости прекратится..... И из всей схемы плавность работает в диапазоне 100-200 мВ...
Либо ставить большую емкость надо, что бы плавносьт была заметна глазу....
"Помоему так" (ц) Иа
Как вариант - вижу перенос светодиода с резистором в эммитерную цепь... получаем каскад с ОК (эммитерный повторитель).
Тогда плавное зажигание светодиода будет начинаться от 1.5-2 вольт на базе (зависит от падения напряжения на переходе светодиода) и до полного питания (в случае 5 вольт питания - диапазон 2..5 вольт).
Либо менять биполярник на какой то полевик низковольтный.
Dimon456, Т.е. с точки зрения оптимизации gcc
static в случае inline-функций - зло?
И кто-нибудь, подскажите сакральный смысл static в определении функций в чистом Си (не ++)?