Страница 1 из 2
указатели в keil
Добавлено: Вт сен 11, 2018 13:42:20
Ser-B
char number_tel_2[ 12 ]="0000000000";
uint32_t *source_addr;
source_addr = (void*)number_tel_2;
temp = *source_addr; // <- здесь происходит зависание.
При выполнениии приведенных операций происходит зависание мк.
Подскажите что я делаю не так.
Re: указатели в keil
Добавлено: Вт сен 11, 2018 14:15:37
BorisSPB
Указатель на uint32_t должен быть выровнен по 32-бита. Ядро Cortex-M не может считывать 32-битные значения с произвольного адреса. При попытке чтения uint32_t с нечетного адреса или адреса кратного 2 происходит прерывание HardFault. Если нужно именно uint32_t придется лепить его из отдельных байтов или прочитать сначала char и привести это значение к uint32_t.
Re: указатели в keil
Добавлено: Вт сен 11, 2018 16:58:15
Sergi
А разве number_tel_2 не указывает на первый символ строки char number_tel_2[]?
Re: указатели в keil
Добавлено: Вт сен 11, 2018 17:10:49
VladislavS
Указывает, но чтение производится 32-битное. По невыровненному адресу.
Re: указатели в keil
Добавлено: Вт сен 11, 2018 17:14:30
Аlex
[uquote="BorisSPB",url="/forum/viewtopic.php?p=3454697#p3454697"]придется лепить его из отдельных байтов или прочитать сначала char и привести это значение к uint32_t.[/uquote] Или просто в union их объединить.
PS: Вообще, странно, что компилятор не выровнял адрес начала массива.
Re: указатели в keil
Добавлено: Вт сен 11, 2018 17:31:07
Reflector
[uquote="Аlex",url="/forum/viewtopic.php?p=3454790#p3454790"]PS: Вообще, странно, что компилятор не выровнял адрес начала массива.[/uquote]
Он выровнял, просто в случае char это равнозначно отсутствию выравнивания. В С++ можно написать:
Код: Выделить всё
alignas(4) char number_tel_2[12] = "0000000000";
В С придется использовать всякие прагмы/атрибуты конкретного компилятора.
И да, почему-то никто не сказал, что проблемы с выравниванием есть только у Cortex-M0, с M3/M4 все будет работать, но чуть медленнее.
Re: указатели в keil
Добавлено: Вт сен 11, 2018 17:44:26
Аlex
Reflector писал(а):Он выровнял,
Если бы он выровнял, проблем не было бы.
Re: указатели в keil
Добавлено: Вт сен 11, 2018 18:20:23
afz
Не пойму, только, зачем манипулировать четырьмя символами, как одним беззнаковым словом? там же явно наблюдаются цифры в ASCII. Какая может быть польза от манипуляций с кодом 0x30303030 ? Как число, оно не годится, как текст - тоже не очень...
Re: указатели в keil
Добавлено: Вт сен 11, 2018 18:31:46
ARV
ну, наверное, сравнивать быстрее числа, чем символы - или 4 символа за раз, или 1...
Re: указатели в keil
Добавлено: Вт сен 11, 2018 19:03:35
Аlex
Сравнение строк через указатели на
int32_t ? Хм... То ещё извращение
Для этого есть стандартные библиотечные функции.
Но мы этого не узнаем. ТС, как и многие другие, - запустит пулю и сидит молча, подсматривает за темой. Ведь то, что он делает, и его код - большой большой секрет !

Re: указатели в keil
Добавлено: Вт сен 11, 2018 19:17:51
VladislavS
Ну тогда давайте похоливарим, а то у нас нерешённые vs остались :
- win vs lin
- avr vs arm
- keil vs все
- swd vs uart
- etc...
Re: указатели в keil
Добавлено: Вт сен 11, 2018 19:19:51
Reflector
[uquote="Аlex",url="/forum/viewtopic.php?p=3454806#p3454806"]Если бы он выровнял, проблем не было бы.[/uquote]
Компилятор выровнял начало массива исходя из размера его элементов, в данном случае у нас массив байт, потому считай никакого выравнивания и нет. Но оно есть

Можно было бы объявить массив как
вот он выровнен по границам 4-х байт, правда строку ему не присвоишь.
Re: указатели в keil
Добавлено: Вт сен 11, 2018 19:46:25
jcxz
[uquote="BorisSPB",url="/forum/viewtopic.php?p=3454697#p3454697"]Указатель на
uint32_t должен быть выровнен по 32-бита. Ядро Cortex-M не может считывать 32-битные значения с произвольного адреса. При попытке чтения uint32_t с нечетного адреса или адреса кратного 2 происходит прерывание
HardFault.[/uquote]
Да ладно?!! Может стоить матчасть подучить прежде чем чушь нести?
Добавлено after 2 minutes 28 seconds:
[uquote="Аlex",url="/forum/viewtopic.php?p=3454875#p3454875"]Ведь то, что он делает, и его код - большой большой секрет !

[/uquote]
Дык - сопрёте же его гениальный код!

Re: указатели в keil
Добавлено: Вт сен 11, 2018 20:00:31
Аlex
НУ почему сразу чушь ?
Проблема действительно имеет место быть. Только не на всех ядрах.
Вот, в точности такая же проблема обсуждается -
http://forum.cxem.net/index.php?/topic/ ... nt=3040527
Добавлено after 10 minutes 39 seconds:
VladislavS писал(а):Компилятор выровнял начало массива исходя из размера его элементов, в данном случае у нас массив байт, потому считай никакого выравнивания и нет. Но оно есть
Согласен. Он выровнял по байту. Для слов (2, 4 байта) уже, считай, что выравнивания нет

По этому и странно, что не положил массив начиная с выровненного по 4 байта поля. Хотя ... хз... хз...

Re: указатели в keil
Добавлено: Вт сен 11, 2018 20:30:31
VladislavS
[uquote="Аlex",url="/forum/viewtopic.php?p=3454915#p3454915"]НУ почему сразу чушь ?[/uquote]Потому что в том виде как оно сформулировано это ложное утверждение. Впрочем, тем кто это понимает цепляться к словам особого смысла нет.
Re: указатели в keil
Добавлено: Вт сен 11, 2018 21:04:33
Z_h_e
Аlex писал(а):По этому и странно, что не положил массив начиная с выровненного по 4 байта поля. Хотя ... хз... хз...

Какие то древние ARMы имели доступ как памяти только выравненный по словам. На пикче слева, видна существенная потеря памяти, против современных, справа. Так что ничего странного.
BorisSPB писал(а):Указатель на uint32_t должен быть выровнен по 32-бита. Ядро Cortex-M не может считывать 32-битные значения с произвольного адреса. При попытке чтения uint32_t с нечетного адреса или адреса кратного 2 происходит прерывание HardFault.
Cortex-M3. Оптимизация выключена.
Код: Выделить всё
volatile uint32_t Buf=0x01020304;
volatile uint32_t *pBuf=&Buf;
Buf=*((uint32_t*)((uint8_t*)pBuf+1));
Код прошагал, исключения не произошло. Buf присвоилось 0x01020304, затем изменилось на 0x88010203.
Ниже дамп памяти. Красным подчернкнут адрес начала дампа, черным Buf после выполнения всего вышеуказанного кода, зеленым указатель.
Ser-B писал(а):
При выполнениии приведенных операций происходит зависание мк.
Надо в отладке поглядеть где висите.
ARV писал(а):ну, наверное, сравнивать быстрее числа, чем символы - или 4 символа за раз, или 1...
32разрядный МК должен работать быстрее с 32 разрядными числами, но душа просит все время 8битные переменные объявлять

, даже очень локальные флаги, которые скорее всего будут в регистре и само-собой займут его весь.
Re: указатели в keil
Добавлено: Вт сен 11, 2018 22:09:49
jcxz
[uquote="VladislavS",url="/forum/viewtopic.php?p=3454955#p3454955"]Впрочем, тем кто это понимает цепляться к словам особого смысла нет.[/uquote]
Вряд-ли это понимает автор темы, так как даже не указал какой у него МК.
Re: указатели в keil
Добавлено: Ср сен 12, 2018 08:57:40
Ser-B
Никакого секрета нет.
Всего лишь хотел передать суть проблемы.
В М3 действительно все было норм, а М0 такая вот ерунда.
Задача записывать во флеш настройки скопом из всех массивов и считывать в массивы при включении мк.
Проблема исчезла при объявлении 32-разрядных массивов. Правда, появился дополнительный расход памяти.
uint32_t adr_sensor[QTY_TERM_SENSOR][8];
uint32_t number_tel[ QTY_NUMBER_TEL ];
float up_alarm_sensor[QTY_TERM_SENSOR];
float down_alarm_sensor[QTY_TERM_SENSOR];
float up_alarm_press_sensor[QTY_PRESS_SENSOR];
float down_alarm_press_sensor[QTY_PRESS_SENSOR];
void FLASH_ReadSettings(void) {
//Read settings
uint16_t i;
uint32_t *source_addr = (uint32_t *)MY_FLASH_PAGE_ADDR;
uint32_t *dest_addr;
dest_addr = (void *)adr_sensor;
for (i=0; i<(QTY_TERM_SENSOR*2); i++) {
*dest_addr = *(__IO uint32_t*)source_addr;
source_addr++;
dest_addr++;
}
dest_addr = (void *)mapping_sensor;
for (i=0; i<QTY_TERM_SENSOR; i++) {
*dest_addr = *(__IO uint32_t*)source_addr;
source_addr++;
dest_addr++;
}
dest_addr = (void *)up_alarm_sensor;
for (i=0; i<QTY_TERM_SENSOR; i++) {
*dest_addr = *(__IO uint32_t*)source_addr;
source_addr++;
dest_addr++;
}
dest_addr = (void *)down_alarm_sensor;
for (i=0; i<QTY_TERM_SENSOR; i++) {
*dest_addr = *(__IO uint32_t*)source_addr;
source_addr++;
dest_addr++;
}
dest_addr = (void *)up_alarm_press_sensor;
for (i=0; i<QTY_PRESS_SENSOR; i++) {
*dest_addr = *(__IO uint32_t*)source_addr;
source_addr++;
dest_addr++;
}
dest_addr = (void *)down_alarm_press_sensor;
for (i=0; i<QTY_PRESS_SENSOR; i++) {
*dest_addr = *(__IO uint32_t*)source_addr;
source_addr++;
dest_addr++;
}
dest_addr = (void *)number_tel;
for (i=0; i<QTY_NUMBER_TEL; i++) {
*dest_addr = *(__IO uint32_t*)source_addr;
source_addr++;
dest_addr++;
}
}
void FLASH_ProgramWord(uint32_t Address, uint32_t data){
//Write to Page
FLASH->CR |= FLASH_CR_PG; //Write 1 to PG (programming bit)
//*pPage = Temperature; //Write to flash page
*(__IO uint16_t*)(Address) = (uint16_t)data; //GET HARDFAULT HERE. CODE FROM ST
while ((FLASH->SR & FLASH_SR_BSY) != 0); //Wait until bus is not busy
if ((FLASH->SR & FLASH_SR_EOP) != 0){ //Check if flash is completed
FLASH->SR |= FLASH_SR_EOP; //Clear flag is flash is complete
}
data >>=16;
Address +=2;
*(__IO uint16_t*)(Address) = (uint16_t)data; //GET HARDFAULT HERE. CODE FROM ST
while ((FLASH->SR & FLASH_SR_BSY) != 0); //Wait until bus is not busy
if ((FLASH->SR & FLASH_SR_EOP) != 0){ //Check if flash is completed
FLASH->SR |= FLASH_SR_EOP; //Clear flag is flash is complete
}
FLASH->CR &= ~FLASH_CR_PG; //Clear prog bit to disable write to flash
}
void FLASH_WriteSettings(void) {
uint16_t i;
// Write settings
uint32_t *source_addr;
uint32_t *dest_addr = (uint32_t *) MY_FLASH_PAGE_ADDR;
// uint32_t temp=0;
//Clear Flags
FLASH->SR |= FLASH_SR_EOP; //Clear end of operation flag
FLASH->SR |= FLASH_SR_WRPRTERR; //Clear write protect error flag
FLASH->SR |= FLASH_SR_PGERR; //Clear programming error
//Unlock Flash
while ((FLASH->SR & FLASH_SR_BSY) != 0); //Wait until flash not busy
if ((FLASH->CR & FLASH_CR_LOCK) != 0){ //If flash is locked, do unlk seq.
FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2;
}
//Erase Page before writing
FLASH->CR |= FLASH_CR_PER; //Enable flash page erase
FLASH->AR = MY_FLASH_PAGE_ADDR; //Set page to erase
FLASH->CR |= FLASH_CR_STRT; //Start erase
while ((FLASH->SR & FLASH_SR_BSY) != 0);//Wait until flash no busy
if ((FLASH->SR & FLASH_SR_EOP) != 0){ //If flash finished operation
FLASH->SR |= FLASH_SR_EOP; //Clear flag
}
FLASH->CR &= ~FLASH_CR_PER; //Disable page erase
source_addr = (void *)adr_sensor;
for (i=0; i<(QTY_TERM_SENSOR*2); i++) {
FLASH_ProgramWord((uint32_t)dest_addr, *source_addr);
source_addr++;
dest_addr++;
}
source_addr = (void *)mapping_sensor;
for (i=0; i<(QTY_TERM_SENSOR/4); i++) {
FLASH_ProgramWord((uint32_t)dest_addr, *source_addr);
source_addr++;
dest_addr++;
}
source_addr = (void *)up_alarm_sensor;
for (i=0; i<(QTY_TERM_SENSOR); i++) {
FLASH_ProgramWord((uint32_t)dest_addr, *source_addr);
source_addr++;
dest_addr++;
}
source_addr = (void *)down_alarm_sensor;
for (i=0; i<(QTY_TERM_SENSOR); i++) {
FLASH_ProgramWord((uint32_t)dest_addr, *source_addr);
source_addr++;
dest_addr++;
}
source_addr = (void *)up_alarm_press_sensor;
for (i=0; i<(QTY_PRESS_SENSOR); i++) {
FLASH_ProgramWord((uint32_t)dest_addr, *source_addr);
source_addr++;
dest_addr++;
}
source_addr = (void *)down_alarm_press_sensor;
for (i=0; i<(QTY_PRESS_SENSOR); i++) {
FLASH_ProgramWord((uint32_t)dest_addr, *source_addr);
source_addr++;
dest_addr++;
}
source_addr = (void *)number_tel;
for (i=0; i<QTY_NUMBER_TEL; i++) {
FLASH_ProgramWord((uint32_t)dest_addr, *source_addr);
source_addr++;
dest_addr++;
}
// FLASH_Lock();
FLASH->CR |= FLASH_CR_LOCK;
}
Re: указатели в keil
Добавлено: Ср сен 12, 2018 09:38:10
Мурик
Z_h_e писал(а):Код прошагал, исключения не произошло.
В M0 будет.
http://purebasic.mybb.ru/viewtopic.php?id=564#p7599
Re: указатели в keil
Добавлено: Ср сен 12, 2018 10:43:07
BorisSPB
Вообще-то, особенности есть:
3.3.5. Address alignment
An aligned access is an operation where a word-aligned address is used for a word, dual word, or multiple word access, or where a halfword-aligned address is used for a halfword access. Byte accesses are always aligned.
The Cortex-M4 processor supports unaligned access only for the following instructions:
LDR, LDRT
LDRH, LDRHT
LDRSH, LDRSHT
STR, STRT
STRH, STRHT
All other load and store instructions generate a UsageFault exception if they perform an unaligned access, and therefore their accesses must be address aligned.
http://infocenter.arm.com/help/index.js ... FAIGG.html
С приведением типов указателей надо быть аккуратнее...