Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
GPIO_InitTypeDef PORT; — дурной тон. Оставьте капс для макрсов.VDD_Pin_Port->ODR |= VDD_Pin; писать стоит очень аккуратно. Это типичная проблема Read-Modify-Write, если на середине эта операция прервется прерыванием, которое тоже что-то запишет в порт — получим редкий и трудноуловимый баг. В GPIO портах STM-ок для этого предусмотрены регистры BSR и BRR, обеспечивающие атомарную запись бита в порт.Вот так: VDD_Pin_Port->ODR |= VDD_Pin; писать стоит очень аккуратно. Это типичная проблема Read-Modify-Write, если на середине эта операция прервется прерыванием, которое тоже что-то запишет в порт — получим редкий и трудноуловимый баг. В GPIO портах STM-ок для этого предусмотрены регистры BSR и BRR, обеспечивающие атомарную запись бита в порт.
И как минимум gcc умеет распознавать такие языковые конструкции и использует для них правильные последовательности команд.
void test_or() {
PORTB |= 1 << 5;
}
void test_and() {
PORTB &= ~(1 << 5);
}
void test_xor() {
PORTB ^= 1 << 5;
}
void test_xor2() {
PORTB ^= ~(1 << 5);
}
void test_or_arg(uint8_t bit) {
PORTB |= 1 << bit;
}
00000000 <test_or>:
0: 2d 9a sbi 0x05, 5 ; 5
2: 08 95 ret
Disassembly of section .text.test_and:
00000000 <test_and>:
0: 2d 98 cbi 0x05, 5 ; 5
2: 08 95 ret
Disassembly of section .text.test_xor:
00000000 <test_xor>:
0: 85 b1 in r24, 0x05 ; 5
2: 90 e2 ldi r25, 0x20 ; 32
4: 89 27 eor r24, r25
6: 85 b9 out 0x05, r24 ; 5
8: 08 95 ret
Disassembly of section .text.test_xor2:
00000000 <test_xor2>:
0: 85 b1 in r24, 0x05 ; 5
2: 9f ed ldi r25, 0xDF ; 223
4: 89 27 eor r24, r25
6: 85 b9 out 0x05, r24 ; 5
8: 08 95 ret
Disassembly of section .text.test_or_arg:
00000000 <test_or_arg>:
0: 95 b1 in r25, 0x05 ; 5
2: 21 e0 ldi r18, 0x01 ; 1
4: 30 e0 ldi r19, 0x00 ; 0
6: 08 2e mov r0, r24
8: 00 c0 rjmp .+0 ; 0xa <test_or_arg+0xa>
a: 22 0f add r18, r18
c: 0a 94 dec r0
e: 02 f4 brpl .+0 ; 0x10 <test_or_arg+0x10>
10: 92 2b or r25, r18
12: 95 b9 out 0x05, r25 ; 5
14: 08 95 ret
Для ^= он такую оптимизацию применить уже не догадывается.
Так для xor вроде бы нету атомарной операции изменения бита?
И обращаться по другому адресу компилятор не в праве.
Видно, что в случае, если компилятор видит |= или &= и на этапе компиляции знает, что в маске только один бит, то он применяет специальные атомарные команды. Для ^= он такую оптимизацию применить уже не догадывается.
PORTB |= (1<<5)|(1<<6); — опять чтение-модификация-запись (по другому ведь нельзя, если не считать, что программист написал бы два sbi, т.к. это выгоднее, но так же небезопасно).
Изучаем STM32 на практике. Часть 1. Подключение экрана от Siemens C55