19.06.2017, 10:00
|
|
Частый гость
Регистрация: 05.10.2007
Сообщений: 19
Сказал спасибо: 0
Сказали Спасибо 3 раз(а) в 3 сообщении(ях)
|
STM32L053 HardFault
В целом или лыжи не едут, или лето настало.
Компилятор KEIL 5.23.
При приеме данных по UART получаю регистры uint16 или uint32 и перед записью в EEPROM вынужден переворачивать их. И тут начинается странное.
void flip_reg(uint16_t* ptr_reg, uint8_t len, uint8_t size)
{uint8_t cnt2;
uint32_t* ptr1, ptr2;
if(size == 2)
{cnt2=len››1;
do
{ptr1 = (uint32_t*)(ptr_reg+(cnt2‹‹1));
*(unsigned short*)ptr1 = swap16(*(unsigned short*)ptr1);
}while(cnt2--);
}
и здесь крашиться в HardFault причем даже в асме подозрений нет.
273: *(unsigned short*)ptr1 = swap16(*(unsigned short*)ptr1);
LDRH r0,[r3,#0x00]
BL.W swap16 (0x08004334)
STRH r0,[r3,#0x00]
274: }while(cnt2--);}
поиск пока ничего не дал. Подскажите куда пинать.
Причем заметил, что ЛЮБОЕ преобразование типа вызывает это прерывание.
|
|
|
|
19.06.2017, 14:35
|
|
Почётный гражданин KAZUS.RU
Регистрация: 24.03.2007
Сообщений: 1,329
Сказал спасибо: 85
Сказали Спасибо 595 раз(а) в 361 сообщении(ях)
|
Re: STM32L053 HardFault
Возможно из-за преобразования uint16_t* в uint32_t*.
Если адрес в ptr_reg не кратен 4.
Попробуйте преобразовать в (__packed uint32_t*).
|
|
|
|
19.06.2017, 14:46
|
|
Почётный гражданин KAZUS.RU
Регистрация: 24.03.2007
Сообщений: 1,329
Сказал спасибо: 85
Сказали Спасибо 595 раз(а) в 361 сообщении(ях)
|
Re: STM32L053 HardFault
Ну, разумеется, при этом ptr1 должна быть объявлена как
__packed uint32_t *ptr1;
Кстати, а ptr2 без знака "*".
Так и надо, или ошибка?
|
|
|
|
19.06.2017, 14:59
|
|
Почётный гражданин KAZUS.RU
Регистрация: 12.02.2013
Сообщений: 1,008
Сказал спасибо: 43
Сказали Спасибо 271 раз(а) в 212 сообщении(ях)
|
Re: STM32L053 HardFault
Сообщение от kampri
|
Подскажите куда пинать.
|
ИМХО вы очень сильно злоупотребляете работой с указателями. Самое простое - считать данные по указателю в локальную переменную функции. Поменять байты местами (в локальной переменной) а потом сохранить новое значение по указателю.
|
|
|
|
19.06.2017, 15:35
|
|
Заблокирован
Регистрация: 22.04.2014
Сообщений: 0
Сказал спасибо: 15
Сказали Спасибо 366 раз(а) в 284 сообщении(ях)
|
Re: STM32L053 HardFault
Сообщение от kampri
|
Компилятор KEIL 5.23.
При приеме данных по UART получаю регистры uint16 или uint32 и перед записью в EEPROM вынужден переворачивать их. И тут начинается странное.
|
В Ф0 есть причуды при работе с невыравненными данными. В Ф1 может и прокатить, но тоже не всегда. Поэтому меняйте подход в целом.
В кортексах есть команды реверса, но в Ф0 они слегка укошенные. Смотрите в систему команд Ф0 для уточнения.
|
|
|
|
19.06.2017, 23:12
|
|
Гражданин KAZUS.RU
Регистрация: 17.06.2008
Адрес: Украина
Сообщений: 664
Сказал спасибо: 360
Сказали Спасибо 743 раз(а) в 353 сообщении(ях)
|
Re: STM32L053 HardFault
Вот на всякий случай ссылка на STM32F0xxx Cortex-M0 programming manual;
Раздел 3.4.2 LDR and STR, immediate offset
Раздел 3.3.4 Address alignment
|
|
|
|
19.06.2017, 23:25
|
|
Почётный гражданин KAZUS.RU
Регистрация: 07.09.2014
Сообщений: 4,418
Сказал спасибо: 395
Сказали Спасибо 2,205 раз(а) в 1,306 сообщении(ях)
|
Re: STM32L053 HardFault
Экую чухню вы наворотили. Начиная с того, что ptr2 не является указателем, он просто переменная.
Ну и сам обмен байтов в 4-байтной переменной выполяется вот так: (для наглядности пишу пошагово)
Код:
|
uint32_t abcd = 0x12345678, dcba = 0;
uint8_t tmp;
uint8_t *ptr_abcd, *ptr_dcba;
ptr_abcd = (uint8_t*)&abcd;
ptr_dcba = (uint8_t*)&dcba;
ptr_dcba +=3;
tmp = *(uint8_t*)ptr_abcd++;
*(uint8_t*)ptr_dcba-- = tmp;
tmp = *(uint8_t*)ptr_abcd++;
*(uint8_t*)ptr_dcba-- = tmp;
tmp = *(uint8_t*)ptr_abcd++;
*(uint8_t*)ptr_dcba-- = tmp;
tmp = *(uint8_t*)ptr_abcd;
*(uint8_t*)ptr_dcba = tmp; |
В цикл лучше не заключать - нафик нужна лишняя переменная и работа с ней, если и так всё понятно
Да, если надо определить размерность переменной для "переворота", используем sizeof(), дополнительного параметра размера не надо:
Код:
|
if (sizeof(abcd) == 4)
{
// ....
}
if (sizeof(abcd) == 2)
{
// ....
} |
Последний раз редактировалось NewWriter; 20.06.2017 в 01:23.
|
|
|
Сказали "Спасибо" NewWriter
|
|
|
20.06.2017, 00:35
|
|
Вид на жительство
Регистрация: 10.06.2007
Сообщений: 429
Сказал спасибо: 34
Сказали Спасибо 51 раз(а) в 47 сообщении(ях)
|
Re: STM32L053 HardFault
kampri, а разве соответствующую инструкцию (rev) нельзя использовать? Или просто нужно чтоб посложнее...?
Раздел 3.5.7 REV, REV16, and REVSH
http://www.st.com/content/ccc/resour...DM00104451.pdf
И есть соответствующие функции в CMSIS:
PHP код:
|
uint32_t __REV(uint32_t value)
uint32_t __REV16(uint32_t value)
int32_t __REVSH(int32_t value)
|
для gcc. И для armcc конечно тоже есть __REV
И вероятность сделать баг на указателях поменьше станет...
|
|
|
|
20.06.2017, 00:58
|
|
Почётный гражданин KAZUS.RU
Регистрация: 12.02.2013
Сообщений: 1,008
Сказал спасибо: 43
Сказали Спасибо 271 раз(а) в 212 сообщении(ях)
|
Re: STM32L053 HardFault
uint8_t temp;
union swap{
uint32_t temp32;
uint8_t temp8[4];
} var;
var.temp32 = чего_хотим_посвопить;
temp = var.temp8[0];
var.temp8[0] = var.temp8[3];
var.temp8[3] = temp;
temp = var.temp8[1];
var.temp8[1] = var.temp8[2];
var.temp8[2] = temp;
|
|
|
|
20.06.2017, 01:04
|
|
Заблокирован
Регистрация: 22.04.2014
Сообщений: 0
Сказал спасибо: 15
Сказали Спасибо 366 раз(а) в 284 сообщении(ях)
|
Re: STM32L053 HardFault
Сообщение от NewWriter
|
Экую чухню вы наворотили.
|
А сам? "Отпусти меня Микрочип, отпусти!"(с)?
Сообщение от H4LF
|
для gcc. И для armcc конечно тоже есть __REV
|
А что... CMSIS для разных компилей может быть разным? Это обёртка для асмовых инструкций, не более.
Сообщение от dgrishin
|
uint8_t temp;
|
Еще лучше и веселее.
Последний раз редактировалось STM32F0; 20.06.2017 в 01:07.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 10:52.
|
|