|
Скопировать часть массива в переменную 64 бита |
|
|
|
Apr 10 2018, 05:07
|
Частый гость
 
Группа: Свой
Сообщений: 97
Регистрация: 27-07-10
Из: харьков
Пользователь №: 58 632

|
Цитата Понимаю что что связанно с адресацией но что именно? unaligned access Используйте memcpy
|
|
|
|
|
Apr 10 2018, 09:57
|
Частый гость
 
Группа: Участник
Сообщений: 153
Регистрация: 29-05-08
Пользователь №: 37 901

|
Цитата(Jenya7 @ Apr 10 2018, 07:59)  а так? Код *((uint64_t *)write_key)) = *((uint64_t *)(rx_buffer+5))); Так тоже не прокатило. Туда же в ошибку и улетает. Да, memcopy то я туда и поставил, только memcopy побайтно копирует, а хотелось по словам.
|
|
|
|
|
Apr 10 2018, 11:00
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Jenya7 @ Apr 10 2018, 07:59)  а так? Код *((uint64_t *)write_key)) = *((uint64_t *)(rx_buffer+5))); Прежде чем что-то советовать надо научиться читать и понимать то, что пишут. Чтобы не писать ерунду. Из контекста исходного сообщения автора видно, что write_key - это не указатель, а переменная в которую нужно записать. Это во-первых. А во-вторых - читайте про невыровненный доступ в Cortex-M. Цитата(IgorAVR2 @ Apr 10 2018, 12:57)  Так тоже не прокатило. Туда же в ошибку и улетает. Для IAR (а может и других компиляторов): Код typedef unsigned long long u64; typedef __packed u64 u64p8; *(u64p8 *)&write_key = *(u64p8 *)&rx_buffer[5]; ...и уже сам компилятор решит какие команды использовать.
|
|
|
|
|
Apr 10 2018, 11:43
|
Частый гость
 
Группа: Участник
Сообщений: 153
Регистрация: 29-05-08
Пользователь №: 37 901

|
Цитата(jcxz @ Apr 10 2018, 14:00)  Код typedef unsigned long long u64; typedef __packed u64 u64p8; *(u64p8 *)&write_key = *(u64p8 *)&rx_buffer[5]; ...и уже сам компилятор решит какие команды использовать. Да, спасибо. Ваш способ подошёл. Но я так понимаю, что так как переменные не выровнены в памяти, то он всё рано будет копировать побайтно. А если делать через memcpy, как советует Kabdim, то компилятор разве не будет побайтно копировать? Пока писал вопрос уже ответили - и я вот сомневаюсь насчёт memcpy.
|
|
|
|
|
Apr 10 2018, 11:44
|
Знающий
   
Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842

|
Зря не верите, все современные компиляторы насколько я знаю оптимизируют это в релизбилде. Другое дело что они не всегда по коду могут сказать что ((uint)(rx_buffer+5) & 3) == 0. Но в этом случае ни один, ни второй метод не будут соптимизирован. Можно сделать аля: Код uint64_t inner_buffer[x]; uint8_t *rx_buffer = static_cast<uint8_t*>(&inner_buffer[0]) + 3; И продолжать жечь в духе первого поста. Только возможно еще и с индексами, а не с адресной арифметикой.
|
|
|
|
|
Apr 10 2018, 12:04
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(IgorAVR2 @ Apr 10 2018, 14:43)  так как переменные не выровнены в памяти, то он всё рано будет копировать побайтно. Нет, если компилятор на этапе сборки кода будет знать, что ((uint)(rx_buffer+5) & 3) == 0, то он использует LDRD или пару LDR. Если нет, но ((uint)(rx_buffer+5) & 1) == 0, то он может использовать LDRH,LDR,LDRH. Если на этапе сборки кода значение rx_buffer неизвестно, то будет использовать побайтный доступ.
|
|
|
|
|
Apr 10 2018, 14:15
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(IgorAVR2 @ Apr 10 2018, 17:02)  Вычитал в в аналогичном топике, что оказывается STM32f4 об этом думать не нужно. Вот и у меня видимо до этого так раньше работало в других проектах. Нет, не поэтому. Не нужно для операций LDR/STR - только они поддерживают невыровненный доступ на M3/M4. А если Вы пишете тип u64, то для работы с таким типом компилятор может применить LDRD/STRD, а эти команды не поддерживают невыровненный доступ даже в M4. Хотя может какой-то конкретный, не очень оптимизирующий компилятор, вместо одной LDRD, может применить пару LDR, тогда прокатит. Но чтобы не гадать, хорошим тоном является явное указание невыровненности переменной (__packed), тогда компилятор сам решит как нужно работать с данной переменной на данном ядре. И не будет сюрпризов при переносе кода на другое ядро. PS: Да и учиться нужно не по "топикам" где могут нести какую угодно чушь, а по мануалам на ядро. Там всё разжёвано.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|