указатели в keil
указатели в keil
char number_tel_2[ 12 ]="0000000000";
uint32_t *source_addr;
source_addr = (void*)number_tel_2;
temp = *source_addr; // <- здесь происходит зависание.
При выполнениии приведенных операций происходит зависание мк.
Подскажите что я делаю не так.
uint32_t *source_addr;
source_addr = (void*)number_tel_2;
temp = *source_addr; // <- здесь происходит зависание.
При выполнениии приведенных операций происходит зависание мк.
Подскажите что я делаю не так.
Re: указатели в keil
Указатель на uint32_t должен быть выровнен по 32-бита. Ядро Cortex-M не может считывать 32-битные значения с произвольного адреса. При попытке чтения uint32_t с нечетного адреса или адреса кратного 2 происходит прерывание HardFault. Если нужно именно uint32_t придется лепить его из отдельных байтов или прочитать сначала char и привести это значение к uint32_t.
Re: указатели в keil
А разве number_tel_2 не указывает на первый символ строки char number_tel_2[]?
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: указатели в keil
Указывает, но чтение производится 32-битное. По невыровненному адресу.
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: указатели в keil
придется лепить его из отдельных байтов или прочитать сначала char и привести это значение к uint32_t.
Или просто в union их объединить.PS: Вообще, странно, что компилятор не выровнял адрес начала массива.
Re: указатели в keil
PS: Вообще, странно, что компилятор не выровнял адрес начала массива.
Он выровнял, просто в случае char это равнозначно отсутствию выравнивания. В С++ можно написать:
Код: Выделить всё
alignas(4) char number_tel_2[12] = "0000000000";В С придется использовать всякие прагмы/атрибуты конкретного компилятора.
И да, почему-то никто не сказал, что проблемы с выравниванием есть только у Cortex-M0, с M3/M4 все будет работать, но чуть медленнее.
Последний раз редактировалось Reflector Вт сен 11, 2018 19:55:06, всего редактировалось 1 раз.
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: указатели в keil
Если бы он выровнял, проблем не было бы.Reflector писал(а):Он выровнял,
- afz
- Опытный кот
- Сообщения: 744
- Зарегистрирован: Сб дек 22, 2012 08:17:42
- Откуда: Караганда, Казахстан
Re: указатели в keil
Не пойму, только, зачем манипулировать четырьмя символами, как одним беззнаковым словом? там же явно наблюдаются цифры в ASCII. Какая может быть польза от манипуляций с кодом 0x30303030 ? Как число, оно не годится, как текст - тоже не очень...
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: указатели в keil
ну, наверное, сравнивать быстрее числа, чем символы - или 4 символа за раз, или 1...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: указатели в keil
Сравнение строк через указатели на int32_t ? Хм... То ещё извращение
Для этого есть стандартные библиотечные функции.
Но мы этого не узнаем. ТС, как и многие другие, - запустит пулю и сидит молча, подсматривает за темой. Ведь то, что он делает, и его код - большой большой секрет !
Для этого есть стандартные библиотечные функции.
Но мы этого не узнаем. ТС, как и многие другие, - запустит пулю и сидит молча, подсматривает за темой. Ведь то, что он делает, и его код - большой большой секрет !
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: указатели в keil
Ну тогда давайте похоливарим, а то у нас нерешённые vs остались :
- win vs lin
- avr vs arm
- keil vs все
- swd vs uart
- etc...
- win vs lin
- avr vs arm
- keil vs все
- swd vs uart
- etc...
Re: указатели в keil
Если бы он выровнял, проблем не было бы.
Компилятор выровнял начало массива исходя из размера его элементов, в данном случае у нас массив байт, потому считай никакого выравнивания и нет. Но оно есть
Код: Выделить всё
int number_tel_2[12 / 4];вот он выровнен по границам 4-х байт, правда строку ему не присвоишь.
Re: указатели в keil
Указатель на uint32_t должен быть выровнен по 32-бита. Ядро Cortex-M не может считывать 32-битные значения с произвольного адреса. При попытке чтения uint32_t с нечетного адреса или адреса кратного 2 происходит прерывание HardFault.
Да ладно?!! Может стоить матчасть подучить прежде чем чушь нести?
Добавлено after 2 minutes 28 seconds:
Ведь то, что он делает, и его код - большой большой секрет ! 
Дык - сопрёте же его гениальный код!
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: указатели в keil
НУ почему сразу чушь ?
Проблема действительно имеет место быть. Только не на всех ядрах.
Вот, в точности такая же проблема обсуждается - http://forum.cxem.net/index.php?/topic/ ... nt=3040527
Добавлено after 10 minutes 39 seconds:

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

- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: указатели в keil
НУ почему сразу чушь ?
Потому что в том виде как оно сформулировано это ложное утверждение. Впрочем, тем кто это понимает цепляться к словам особого смысла нет.- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: указатели в keil
Какие то древние ARMы имели доступ как памяти только выравненный по словам. На пикче слева, видна существенная потеря памяти, против современных, справа. Так что ничего странного.Аlex писал(а):По этому и странно, что не положил массив начиная с выровненного по 4 байта поля. Хотя ... хз... хз...
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 писал(а):При выполнениии приведенных операций происходит зависание мк.
32разрядный МК должен работать быстрее с 32 разрядными числами, но душа просит все время 8битные переменные объявлятьARV писал(а):ну, наверное, сравнивать быстрее числа, чем символы - или 4 символа за раз, или 1...
Re: указатели в keil
Впрочем, тем кто это понимает цепляться к словам особого смысла нет.
Вряд-ли это понимает автор темы, так как даже не указал какой у него МК.
Re: указатели в keil
Никакого секрета нет.
Всего лишь хотел передать суть проблемы.
В М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;
}
Всего лишь хотел передать суть проблемы.
В М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
В M0 будет. http://purebasic.mybb.ru/viewtopic.php?id=564#p7599Z_h_e писал(а):Код прошагал, исключения не произошло.
Re: указатели в keil
Вообще-то, особенности есть:
http://infocenter.arm.com/help/index.js ... FAIGG.html
С приведением типов указателей надо быть аккуратнее...
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
С приведением типов указателей надо быть аккуратнее...
