Ошибка программы при своевременном разыменовании 64-битного int
Мой код ведет себя странно. Следующее работает без проблем на Arduino Nano, но, похоже, дает сбой на DUE
void putData64(byte* packet, int pos, uint64_t data)
{
uint64_t* h= (uint64_t*) (packet+pos+2);
*h= data;
}
Проблемная строка, похоже, вторая (*h= data), поскольку ее закомментирование позволяет программе работать без проблем.
Аналогично, следующие строки вызывают проблему на DUE, но нормально работают на Nano:
char* data;
// ... данные чем-то заполнены
uint64_t* t= (uint64_t*) (data+1);
uint64_t test= *t;
Что-то мне не хватает?
@user2912328, 👍1
Обсуждение1 ответ
Лучший ответ:
Я согласен с комментарием Маженко: возможно, это выравнивание памяти.
проблема. Я не знаю особенностей Due, но при доступе
памяти в виде блоков 32-битных слов данных на 32-битном процессоре, он может
случается, что архитектура требует, чтобы слова данных были выровнены по
Границы 32 бита (т.е. 4 байта). Это означает, что адрес
uint32_t
или uint64_t
должно быть кратно 4. Может быть
даже 8 для uint64_t
, вам придется проверить.
Единственное решение этой проблемы — заполнить пакет побайтно:
void putData64(byte* packet, int pos, uint64_t data)
{
union {
uint64_t integer;
byte bytes[8];
} h = { .integer = data };
for (int i = 0; i < 8; i++) {
packet[pos+2+i] = h.bytes[i];
}
}
Обратите внимание, что AVR (в Nano) представляет собой 8-битную архитектуру без каких-либо какие бы то ни было ограничения выравнивания.
Спасибо. Я знал о факте 8-битного и 32-битного. Я не пробовал ваш код, но он кажется правильным. В конце концов, трюк для меня заключался в следующем: void putData64 (пакет байт*, int pos, данные uint64_t) { uint32_t* out= (uint32_t*) (пакет+pos+2); uint32_t* in= (uint32_t*) данные; *(выход++)= *(вход++); *(выход++)= *(вход++); }, @user2912328
@ user2912328: Вы имеете в виду in = (uint32_t*) &data
? Обратите внимание: хотя это и может сработать, это довольно хрупко. Если вы не сможете доказать, что packet+pos+2
_всегда_ кратен 4, существует риск того, что out
окажется неправильно выровненным (и, следовательно, недействительным) указателем. Если у вас нет гарантий выравнивания packet+pos+2
, единственным допустимым решением является копирование данных побайтово., @Edgar Bonet
да, вы правы по обоим пунктам. Отсутствует & и кратное 4, @user2912328
- Arduino Due vs Mega 2560
- Точность часов времени Arduino
- Регистры ввода-вывода SAM3X8E (Arduino Due)
- Построение графика на Python с использованием Tkinter Canvas
- Ручная установка Arduino Due
- analogRead всегда 1023 на Arduino Due
- Как выбрать пару SDA/SCL на Arduino Due?
- Как упаковать 16-битное целое число, чтобы отправить его с помощью serial.write?
Вероятно, проблема с выравниванием памяти., @Majenko
Что ты пытаешься сделать? Если вы хотите использовать байты и указатели на байты, это нормально. Если вы хотите использовать 64-битную версию и указатели на нее, это тоже нормально. Но вы смешали эти два понятия. Зачем вам указывать на полпути к 64-битному значению? Предлагаю начать сначала., @Jot