AVR GCC изменение переменной 8bit вне прерывания

Обсуждаем контроллеры компании Atmel.
Ответить
Simon.S
Первый раз сказал Мяу!
Сообщения: 23
Зарегистрирован: Пн дек 15, 2025 13:29:04

AVR GCC изменение переменной 8bit вне прерывания

Сообщение Simon.S »

Опять, без надобности, полез в глухие дебри - вроде и размер прошивки устраивает и отзывчатость, но решил посмотреть что получается при использовании структур.

Задача простая вне прерывания получать менять 8-битную переменную. Вроде как не нужно атомарный доступ. Решил глянуть, что выдаст асемблер.

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


typedef struct {
	bool test : 1;
	bool _unused1 : 1;
	bool _unused2 : 1;
	bool _unused3 : 1;
	bool _unused4 : 1;
	bool _unused5 : 1;
	bool _unused6 : 1;
	bool _unused7 : 1;
} compare_enabled_t;

typedef struct {
	...
	compare_enabled_t is_enabled;
	byte_t x;
} clock_struct_t;

использование

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

volatile clock_struct_t clock = { ... , .test = {0}, .is_enabled = {.test = false}}; 
byte_t clock_x = 0;
void on_lo_press(void) {
	printf("on_lo_long\n");
	_NOP();
	clock.is_enabled.test = false;
	_NOP();
	clock.x &= ~_BV(0);
	_NOP();
	clock_x &= ~_BV(0);
	_NOP();
	clock.x &= 32;
	_NOP();
	clock_x = 32;
	_NOP();
}
Стандартная оптимизация по размеру, О2 оптимизация и О3 оптимизация дают здесь одинаковый ассемблерный код(хотя в общем размер бинарника Os/O2 отличается на 25%):

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

/* #APP */
 ;  30 "modules/buttons.c" 1
	nop
 ;  0 "" 2
/* #NOAPP */
	ldi r30,lo8(clock+10)
	ldi r31,hi8(clock+10)
	ld r24,Z
	andi r24,lo8(~(1<<0))
	st Z,r24
/* #APP */
 ;  32 "modules/buttons.c" 1
	nop
 ;  0 "" 2
/* #NOAPP */
	ldi r30,lo8(clock)
	ldi r31,hi8(clock)
	ldd r24,Z+11
	andi r24,lo8(-2)
	std Z+11,r24
/* #APP */
 ;  34 "modules/buttons.c" 1
	nop
 ;  0 "" 2
/* #NOAPP */
	lds r24,clock_x
	andi r24,lo8(-2)
	sts clock_x,r24
/* #APP */
 ;  36 "modules/buttons.c" 1
	nop
 ;  0 "" 2
/* #NOAPP */
	ldd r24,Z+11
	andi r24,lo8(32)
	std Z+11,r24
/* #APP */
 ;  38 "modules/buttons.c" 1
	nop
 ;  0 "" 2
/* #NOAPP */
	ldi r24,lo8(32)
	sts clock_x,r24
/* #APP */
В итоге вместо одного вопроса возникло целых два:
1) когда нельзя неатомарно менять переменную? Про аккуратность с некоторыми регистрами знаю(иногда лучше присвоение).
2) зачем такие костыли со структурами? Почему компилятор не может вычислить адрес относительно начала структуры? Выходит даже структуры - это зло. А я хотел в основном цикле много чего творить со сделанной атомарно копией структуры, а затем, если надо, атомарно менять оригинал(или не атомарно, если член 8bit). Что же тогда на ардуино где и классы присутствуют творится...

Добавлено after 36 minutes 6 seconds:
P.S. Работа по ссылке уже интересней:
Спойлер

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

/* #APP */
 ;  30 "modules/buttons.c" 1
	nop
 ;  0 "" 2
/* #NOAPP */
	ldd r24,Z+10
	andi r24,lo8(~(1<<0))
	std Z+10,r24
/* #APP */
 ;  32 "modules/buttons.c" 1
	nop
 ;  0 "" 2
/* #NOAPP */
	ldd r24,Z+11
	andi r24,lo8(-2)
	std Z+11,r24
/* #APP */
 ;  34 "modules/buttons.c" 1
	nop
 ;  0 "" 2
/* #NOAPP */
	lds r24,clock_x
	andi r24,lo8(-2)
	sts clock_x,r24
/* #APP */
 ;  36 "modules/buttons.c" 1
	nop
 ;  0 "" 2
/* #NOAPP */
	ldd r24,Z+11
	andi r24,lo8(32)
	std Z+11,r24
/* #APP */
 ;  38 "modules/buttons.c" 1
	nop
 ;  0 "" 2
/* #NOAPP */
	ldi r24,lo8(32)
	sts clock_x,r24
/* #APP */
 ;  40 "modules/buttons.c" 1
	nop
 ;  0 "" 2
/* #NOAPP */
А я много лет считал, что это для программиста отличается...

Добавлено after 4 hours 12 minutes 26 seconds:
P.P.S. Похоже я пере-перестраховался, так что испугался или наоборот :-) Счетчик и члены сравнения меняются из прерывания по таймеру, а читаются в основном цикле - тут нужно атомарное копирование, а все остальное настройки меняются и читаются только в основном цикле, так что пофиг сколько они занимают байт, всё должно быть OK.

Ну, а что касается структур - тут всё странно:

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

	clock_struct_t _approx_clock;
	const clock_struct_t * approx_clock;
	while(1) {
		_approx_clock = get_current_copy_atomic();
		approx_clock = &_approx_clock;
		...
	}
и

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

	clock_struct_t approx_clock;
	while(1) {
		approx_clock = get_current_copy_atomic();
		...
	}
Дают абсолютно одинаковый ассемблерный код. Причём, оптимальный.
veso74
Поставщик валерьянки для Кота
Сообщения: 1902
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

Re: AVR GCC изменение переменной 8bit вне прерывания

Сообщение veso74 »

[uquote="Simon.S",url="/forum/viewtopic.php?p=4776331#p4776331"]Дают абсолютно одинаковый ассемблерный код.[/uquote]
Нет информации где выполняете компиляцию. Отключите оптимизацию для анализа, если этого еще не сделали.
Simon.S
Первый раз сказал Мяу!
Сообщения: 23
Зарегистрирован: Пн дек 15, 2025 13:29:04

Re: AVR GCC изменение переменной 8bit вне прерывания

Сообщение Simon.S »

[uquote="veso74",url="/forum/viewtopic.php?p=4776425#p4776425"][uquote="Simon.S",url="/forum/viewtopic.php?p=4776331#p4776331"]Дают абсолютно одинаковый ассемблерный код.[/uquote]
Нет информации где выполняете компиляцию. Отключите оптимизацию для анализа, если этого еще не сделали.[/uquote]

GNU AVR toolchain, IDE: Code::Blocks, OS: Gentoo

В том и дело что СО ВСЕМИ оптимизациями которые я знаю, непосредственная работа с глобальной переменной не давала нормального ASM-кода в определения адреса члена структуры, как только заменил на ссылку - адрес стал определяться за одну операцию. Но это в отдельных *.с файлах, где через заголовок было только объявление. Последний же случай в главном файле где эта структура определена. Возможно это каким-то образом повлияло.

[uquote="veso74",url="/forum/viewtopic.php?p=4776425#p4776425"]Отключите оптимизацию для анализа, если этого еще не сделали.[/uquote]
Короче, уже наигрался со всеми возможными, вариантами и с оптимизацией и без. В принципе понятно, что лучше объявление глобальной ссылки на структруру, чем глобальной структуры. Пусть даже, благодаря объявлению, она могла бы быть видна везде, где нужно.

Добавлено after 7 minutes 43 seconds:
Со структурой код проще, всё сгруппировано вместе. Сложнее что-то пропустить.

[uquote="Simon.S",url="/forum/viewtopic.php?p=4776435#p4776435"]Последний же случай в главном файле где эта структура определена. Возможно это каким-то образом повлияло.[/uquote]
Нет не это. Это когда я работал с локальной переменной, содержащей копию структуры. Это и есть ключевое отличие.
Последний раз редактировалось Simon.S Вт дек 30, 2025 20:43:28, всего редактировалось 3 раза.
veso74
Поставщик валерьянки для Кота
Сообщения: 1902
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

Re: AVR GCC изменение переменной 8bit вне прерывания

Сообщение veso74 »

Есть цель? Напр. небольшой объем данных/память или быстрый алгоритм, или просто экспериментируете? Для использования кода в других проектах было бы хорошо, если бы глобальные ресурсы (переменные, структуры и т. д.) действительно были глобальными, а все остальное - локальным, статик, external и т. д. Переключитесь на другой (неограниченный) MK (напр. ARM), там ситуация значительно сложнее.
Simon.S
Первый раз сказал Мяу!
Сообщения: 23
Зарегистрирован: Пн дек 15, 2025 13:29:04

Re: AVR GCC изменение переменной 8bit вне прерывания

Сообщение Simon.S »

[uquote="veso74",url="/forum/viewtopic.php?p=4776439#p4776439"]Есть цель: например, небольшой объем данных/память или быстрый алгоритм, или просто экспериментируете? Для использования кода в других проектах было бы хорошо, если бы глобальные ресурсы (переменные, структуры и т. д.) действительно были глобальными, а все остальное - локальным. Переключитесь на другой (неограниченный) MK (напр. ARM), там ситуация значительно сложнее.[/uquote]

Эксперементирую. Хотелось бы быстрый алгоритм, пока с недостатком памяти никогда не сталкивался, но пока ничего слишком серьёзного на AVR не кодил. Сейчас проект будет довольно сложный и довольно ответственный. Но думаю в размер всё равно впишусь.

Добавлено after 1 minute 49 seconds:
Когда закончу подготовительную часть (в основном учебно-эксперементальную) начну писать контроллер управления аквариумом: температура, насосы, свет.
veso74
Поставщик валерьянки для Кота
Сообщения: 1902
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

Re: AVR GCC изменение переменной 8bit вне прерывания

Сообщение veso74 »

[uquote="Simon.S",url="/forum/viewtopic.php?p=4776441#p4776441"]... писать контроллер управления аквариумом[/uquote]
В ATtiny13A все соберется :). Если нет, прежде чем сказать: не может, выбираем другой MK - это предпосылка для написания действительно сжатого кода. Не обязательно на ASM :).
Simon.S
Первый раз сказал Мяу!
Сообщения: 23
Зарегистрирован: Пн дек 15, 2025 13:29:04

Re: AVR GCC изменение переменной 8bit вне прерывания

Сообщение Simon.S »

[uquote="veso74",url="/forum/viewtopic.php?p=4776449#p4776449"]В ATtiny13A все соберется :)[/uquote]
В наличии только Attiny88 и пара Amega328P :twisted: . Сегодня STM32F405 получил, но в STM пока не умею :dont_know:
Ответить

Вернуться в «AVR»