Кто любит RISC в жизни, заходим, не стесняемся.
Вт дек 17, 2019 15:43:00
И в ODR будет 0x5555.
Если старшее полуслово не используется, то почему бы и нет? Вполне работоспособная схема. Хоть и теоретически это UB.
Я, кстати, в какой-то железяке так гонял байты при помощи DMA - именно из массива uint8_t. Чтобы обеспечить параллельный интерфейс. Старшее полуслово не использовал, поэтому никаких косяков не было. Понятно, что если бы возникла необходимость использовать ногодрыг на пинах старшего полуслова, пришлось бы уже от uint8_t в массиве переходить на uint32_t и писать не в ODR, а в BSRR.
Последний раз редактировалось
Eddy_Em Вт дек 17, 2019 15:45:01, всего редактировалось 1 раз.
Вт дек 17, 2019 15:45:14
Если закоментировать LCD_WR_H; изображения нет.
А откуда ему взяться, если ты в примерно половине случаев WR=1 не делаешь?
Я думал что такой подход кому-то поможет. Применять или нет дело программера.
Мы же с
Reflector показали, что это НЕ РАБОТАЕТ.
Добавлено after 1 minute 21 second:Если старшее полуслово не используется, то почему бы и нет?
Ты вообще читаешь что люди пишут? Используется и влияет!
Вт дек 17, 2019 15:47:16
https://www.youtube.com/watch?v=uv0sqAAMHFA
А что это там за черная фиговина прицеплена к "таблетке"? Холл что ли?
Добавлено after 50 seconds:Ты вообще читаешь что люди пишут? Используется и влияет!
На кой черт я буду лезть дальше двух-трех последних комментариев? Как будто делать нехрен, только всю ветку читать…
Вт дек 17, 2019 15:51:02
И ведь в RM есть прямой запрет так делать, а нет, всё равно советуют...
Вт дек 17, 2019 15:55:06
VladislavS, а не пофиг ли, что в RM запрещено?
Еще раз: если из порта используется только половина ног, скажем младшее полуслово, то вполне нормально писать при помощи DMA байтики в ODR! Это не приведет к поломке устройства или UB, покуда ноги второго полуслова настроены как аналоговые входы или alternate function.
Вт дек 17, 2019 15:58:24
Черная - пьезопищалка. Изначально было про 8бит АЦП.
Вт дек 17, 2019 16:04:27
Еще раз: если из порта используется только половина ног, скажем младшее полуслово, то вполне нормально писать при помощи DMA байтики в ODR!
Sergi писал, что у него на второй половине порта, которая перезаписывается случайным образом, висит WR, энкодер, кнопки и EPROM. По-моему тут и один дисплей не должен нормально работать, разве что на очень низкой скорости, но если очень хочется отлавливать непонятно откуда взявшиеся баги, то почему нет
И это все ради одной или двух лишних инструкций которые добавятся если в половинку порта писать через BSRR.
Вт дек 17, 2019 16:09:03
Reflector, ну, понятно к чему дело - попытка сэкономить время и объем памяти, т.к. через BSRR пришлось бы городить преобразование 8 бит в 32 (единички - в одну половинку, нулики инвертировать - и в другую). А потом при помощи DMA гнать этот массив.
А насчет АЦП - если работает, ну и хрен с ним! Скажем, в STM8 было важно, в какой последовательности считываются полуслова (кажись, это в АЦП было, хотя точно уж не помню). Здесь же никаких флагов нет. Единственная проблема - невыровненный доступ. Но, к счастью, STM32 - little endian, а читать надо младший байт. Так что, все ОК.
Вт дек 17, 2019 16:23:46
VladislavS, а не пофиг ли, что в RM запрещено?
Да, знаю, а если не будет работать "перепишешь модуль ядра".
Добавлено after 5 minutes 55 seconds:через BSRR пришлось бы городить преобразование 8 бит в 32 (единички - в одну половинку, нулики инвертировать - и в другую).
Ууууу, да ты ещё и не знаешь как BSRR работает! Куда я попал...
Вт дек 17, 2019 16:35:51
VladislavS, в смысле не знаю? Одна половинка регистра устанавливает биты, другая - гасит. Что-то ты гонишь!
Вт дек 17, 2019 16:40:00
Если установлены и Set, и Reset биты одновременно, то приоритет имеет Set. Соответственно, ничего инвертировать и в другую половинку гнать не надо. Это, кстати, тоже в RM написано. Да кто же его читает...
Вт дек 17, 2019 16:57:35
Это да, в левую половинку можно просто FFFF положить, а не инверсию нулей.
Вт дек 17, 2019 17:10:51
Нельзя туда FFFF положить! Иначе UB будет. Только FF куда нужно.
Да кто же его читает...
Есть такое.
Вт дек 17, 2019 18:45:38
Почему вдруг?
Если мне надо в порт положить, например, число 0x5555, можно его просто в ODR записать, либо в BSRR положить 0xFFFF5555.
Или, если надо в младший байт число 0x55 записать, просто в BSRR положить 0x00FF0055. Какие-то дополнительные манипуляции с нулями (0x55 => 0xAA => 00AA0055) не нужны.
Ср дек 18, 2019 03:59:05
WiseLord если нужно только записать данные использовать надо ODR, если нужно изменить значение порта есть два путя
1. через read IDR/ODR-modify-write ODR
2. Атомарный write BSRR(установка/сброс) регистр. либо просто атомарный BRR(сброс)
BSRR регистр за один вызов изменяет значение порта, это нужно если работает ОС и несколько потоков могут одновременно получить доступ к порту.
BRR только сбрасывает.
если в переменной лежит число 0x55, вам еще подготовить его надо будет. Если не используется несколько потоков, с атомарным доступом не надо морочиться. Программируете стандартно.
Ср дек 18, 2019 06:34:20
Проверил скорость вех вариантов.
BSRR победил как всегда
.
- Код:
void lcd_send_cmd(uint8_t cmd)
{
LCD_DC_L;
LCD_WR_L;
//GPIOB->ODR &=~0xff00;GPIOB->ODR |= (cmd<<8); //88596 tics
GPIOB->BSRR = 0xff000000 | (cmd<<8); //66660 tics
//LCD = cmd; //72593 tics
LCD_WR_H;
LCD_DC_H;
};
Ср дек 18, 2019 07:24:40
Если не используется несколько потоков, с атомарным доступом не надо морочиться.
Кроме потоков есть ещё и прерывания.
Программируете стандартно.
Через BSRR это и есть стандартно, ибо тупо быстрее, чем R-M-W ODR.
Ср дек 18, 2019 07:30:53
VladislavS есть переменная которая меняется скажем uint8_ t X, как будешь записывать значение в порт через BSRR? Покажи код.
Прерывания другая история, это все равно контроллируемый код и однопоточный.
Ср дек 18, 2019 08:35:22
VladislavS есть переменная которая меняется скажем uint8_ t X, как будешь записывать значение в порт через BSRR?
Да элементарно: GPIOX->BSRR = 0xff0000 | X
Ср дек 18, 2019 13:49:54
VladislavS есть переменная которая меняется скажем uint8_ t X, как будешь записывать значение в порт через BSRR? Покажи код.
Ну, в отличии от Эдика, я парень хитрый. К тому же, ты решил поиграть на моём поле.
Код то будет простой.
- Код:
uint8_t X = GPIOA->IDR; // Сделаем чтобы X была переменной, а не константой
PinList<GpioB<0xFF00>> bus8bit; // Определим шину на старшие 8 бит GPIOB
bus8bit = X; // Запишем в неё данные
А вот во что это скомпилируется, это как раз и интересно. А вариантов тут может быть два.
1. На процессоре STM32F103 без байтового доступа к регистрамКомпилятор выберет вот такой метод и запишет через BSRR
- Код:
template<uint32_t PM=PinsMask>
static void inline write(uint16_t data)
{
if constexpr (PM == 0xFFFF)
base()->ODR = data;
else
base()->BSRR = (PM << 16) | (data & PM);
}
Листинг
- Код:
//uint8_t X = GPIOA->IDR;
LDR.N R1,??main_0 ;; 0x40010808
LDR R0,[R1, #+0]
//PinList<GpioB<0xFF00>> bus8bit;
//bus8bit = X;
LSLS R0,R0,#+24
LSRS R0,R0,#+16
ORR R0,R0,#0xFF000000
STR R0,[R1, #+1032]
2. На процессоре STM32F303 c байтовым доступом к регистрамКомпилятор выберет вот такой метод и запишет через ODR
- Код:
template<uint32_t PM=PinsMask>
static void inline write(uint16_t data)
{
if constexpr (PM == 0xFFFF)
base()->ODR = data;
else if constexpr (PM == 0x00FF)
*(volatile uint8_t*)&base()->ODR = data;
else if constexpr (PM == 0xFF00)
*((volatile uint8_t*)&base()->ODR + 1) = data >> 8;
else
base()->BSRR = (PM << 16) | (data & PM);
}
Листинг
- Код:
//uint8_t X = GPIOA->IDR;
LDR.N R0,??main_0 ;; 0x48000010
LDR R1,[R0, #+0]
//PinList<GpioB<0xFF00>> bus8bit;
//bus8bit = X;
STRB R1,[R0, #+1029]
Ну вот как-то так.
Прерывания другая история, это все равно контроллируемый код и однопоточный.
Хм. Если в основном цикле я делаю неатомарный доступ R-M-W к порту и из прерывания к этому же порту идёт обращение... То всё!
Добавлено after 4 hours 17 minutes 21 second:Ну куда же вы все разбежались? Я ещё не показал коронный номер, которому меня
Reflector научил.
Копируем младшие 8 бит порта в старшие 8 бит в обратном порядке: PB0->PB15, PB1->PB14, PB2->PB13, PB3->PB12, PB4->PB11, PB5->PB10, PB6->PB9 и PB7->PB8.
- Код:
PinList<PB_7, PB_6, PB_5, PB_4, PB_3, PB_2, PB_1, PB_0 > bus_low;
PinList<PB_8, PB_9, PB_10, PB_11, PB_12, PB_13, PB_14, PB_15> bus_high;
bus_high = bus_low;
//Листинг
LDR.N R1,??main_0 ;; 0x48000410
LDRB R0,[R1, #+0]
RBIT R0,R0
LSRS R0,R0,#+24
STRB R0,[R1, #+5]
Powered by phpBB © phpBB Group.
phpBB Mobile / SEO by Artodia.