Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

указатели в keil

Вт сен 11, 2018 13:42:20

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

Указатель на uint32_t должен быть выровнен по 32-бита. Ядро Cortex-M не может считывать 32-битные значения с произвольного адреса. При попытке чтения uint32_t с нечетного адреса или адреса кратного 2 происходит прерывание HardFault. Если нужно именно uint32_t придется лепить его из отдельных байтов или прочитать сначала char и привести это значение к uint32_t.

Re: указатели в keil

Вт сен 11, 2018 16:58:15

А разве number_tel_2 не указывает на первый символ строки char number_tel_2[]?

Re: указатели в keil

Вт сен 11, 2018 17:10:49

Указывает, но чтение производится 32-битное. По невыровненному адресу.

Re: указатели в keil

Вт сен 11, 2018 17:14:30

придется лепить его из отдельных байтов или прочитать сначала char и привести это значение к uint32_t.
Или просто в union их объединить.

PS: Вообще, странно, что компилятор не выровнял адрес начала массива.

Re: указатели в keil

Вт сен 11, 2018 17:31:07

PS: Вообще, странно, что компилятор не выровнял адрес начала массива.

Он выровнял, просто в случае char это равнозначно отсутствию выравнивания. В С++ можно написать:
Код:
alignas(4) char number_tel_2[12] = "0000000000";

В С придется использовать всякие прагмы/атрибуты конкретного компилятора.
И да, почему-то никто не сказал, что проблемы с выравниванием есть только у Cortex-M0, с M3/M4 все будет работать, но чуть медленнее.
Последний раз редактировалось Reflector Вт сен 11, 2018 19:55:06, всего редактировалось 1 раз.

Re: указатели в keil

Вт сен 11, 2018 17:44:26

Reflector писал(а):Он выровнял,
Если бы он выровнял, проблем не было бы.

Re: указатели в keil

Вт сен 11, 2018 18:20:23

Не пойму, только, зачем манипулировать четырьмя символами, как одним беззнаковым словом? там же явно наблюдаются цифры в ASCII. Какая может быть польза от манипуляций с кодом 0x30303030 ? Как число, оно не годится, как текст - тоже не очень...

Re: указатели в keil

Вт сен 11, 2018 18:31:46

ну, наверное, сравнивать быстрее числа, чем символы - или 4 символа за раз, или 1...

Re: указатели в keil

Вт сен 11, 2018 19:03:35

Сравнение строк через указатели на int32_t ? Хм... То ещё извращение :)))
Для этого есть стандартные библиотечные функции.
Но мы этого не узнаем. ТС, как и многие другие, - запустит пулю и сидит молча, подсматривает за темой. Ведь то, что он делает, и его код - большой большой секрет ! :)))

Re: указатели в keil

Вт сен 11, 2018 19:17:51

Ну тогда давайте похоливарим, а то у нас нерешённые vs остались :
- win vs lin
- avr vs arm
- keil vs все
- swd vs uart
- etc...

Re: указатели в keil

Вт сен 11, 2018 19:19:51

Если бы он выровнял, проблем не было бы.

Компилятор выровнял начало массива исходя из размера его элементов, в данном случае у нас массив байт, потому считай никакого выравнивания и нет. Но оно есть :) Можно было бы объявить массив как
Код:
int number_tel_2[12 / 4];

вот он выровнен по границам 4-х байт, правда строку ему не присвоишь.

Re: указатели в keil

Вт сен 11, 2018 19:46:25

Указатель на uint32_t должен быть выровнен по 32-бита. Ядро Cortex-M не может считывать 32-битные значения с произвольного адреса. При попытке чтения uint32_t с нечетного адреса или адреса кратного 2 происходит прерывание HardFault.

Да ладно?!! Может стоить матчасть подучить прежде чем чушь нести? 8)

Добавлено after 2 minutes 28 seconds:
Ведь то, что он делает, и его код - большой большой секрет ! :)))

Дык - сопрёте же его гениальный код! :)))

Re: указатели в keil

Вт сен 11, 2018 20:00:31

НУ почему сразу чушь ?
Проблема действительно имеет место быть. Только не на всех ядрах.
Вот, в точности такая же проблема обсуждается - http://forum.cxem.net/index.php?/topic/ ... nt=3040527

Добавлено after 10 minutes 39 seconds:
VladislavS писал(а):Компилятор выровнял начало массива исходя из размера его элементов, в данном случае у нас массив байт, потому считай никакого выравнивания и нет. Но оно есть :)
Согласен. Он выровнял по байту. Для слов (2, 4 байта) уже, считай, что выравнивания нет :)
По этому и странно, что не положил массив начиная с выровненного по 4 байта поля. Хотя ... хз... хз... :dont_know:

Re: указатели в keil

Вт сен 11, 2018 20:30:31

НУ почему сразу чушь ?
Потому что в том виде как оно сформулировано это ложное утверждение. Впрочем, тем кто это понимает цепляться к словам особого смысла нет.

Re: указатели в keil

Вт сен 11, 2018 21:04:33

Аlex писал(а):По этому и странно, что не положил массив начиная с выровненного по 4 байта поля. Хотя ... хз... хз... :dont_know:
Какие то древние 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битные переменные объявлять :), даже очень локальные флаги, которые скорее всего будут в регистре и само-собой займут его весь.
Вложения
dump.png
(10.03 KiB) Скачиваний: 971
mem.png
(201.22 KiB) Скачиваний: 973

Re: указатели в keil

Вт сен 11, 2018 22:09:49

Впрочем, тем кто это понимает цепляться к словам особого смысла нет.

Вряд-ли это понимает автор темы, так как даже не указал какой у него МК.

Re: указатели в keil

Ср сен 12, 2018 08:57:40

Никакого секрета нет.
Всего лишь хотел передать суть проблемы.
В М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

Вообще-то, особенности есть:
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
С приведением типов указателей надо быть аккуратнее...
Ответить