реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Keil. Не работает код, typedef struct
MySOL
сообщение May 11 2014, 13:41
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 67
Регистрация: 17-06-12
Пользователь №: 72 370



Здравствуйте, товарищи! Прошу помочь разобраться в проблеме. Сам новичок и для написания программы решил разобраться в такой теме как "typedef struct", которая очень полезна при реализации различных интерфейсов (spi, ethernet и прочее). Написал простенькую программу, дабы протестировать и найти возможные подводные камни. Код следующий
Код
void f1(uint16_t *f1_var1);

typedef struct type1                          
{
    uint8_t var1;
    uint8_t var2;
} type1_t;

int __main(void)
{
        type1_t *main_var;                
    
        main_var->var1    =    0xFF;        
        main_var->var2    =    0xFF;

    f1((uint16_t*)main_var);

}

void f1(uint16_t *f1_var1)
{
    *f1_var1    =    *f1_var1>>1;
}


Суть программы заключается в формировании пакета данных, состоящего из двух наборов данных (в данном случае var1 и var2) формата uint8_t вызов функции, которая эти данные обрабатывает.
Проблема заключается в том, что данные 0xFF не записываются в var1 и var2. С чем это связанно не знаю. Тут значения переменных на этапах отладки
Прикрепленное изображение

Прикрепленное изображение

Прикрепленное изображение

Прикрепленное изображение


Прикрепленное изображение

Прошу помочь с проблемой.

Сообщение отредактировал MySOL - May 11 2014, 13:42
Go to the top of the page
 
+Quote Post
Палыч
сообщение May 11 2014, 13:55
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Вы забыли свою структуру где либо разместить (выделить под неё память).
Go to the top of the page
 
+Quote Post
kolobok0
сообщение May 11 2014, 14:00
Сообщение #3


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(MySOL @ May 11 2014, 17:41) *
.. Прошу помочь...


ответ прозвучал уже, ну и ышо пять копеек: о выравнивании не забудьте. либо прямо в коде сохраняете старое, ставите прагмой новое,
после возвращаете старое. либо глобально на весь проект через ключики компиляции...

Сообщение отредактировал kolobok0 - May 11 2014, 14:01
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение May 11 2014, 14:03
Сообщение #4


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Код
typedef struct type1                          
{
    uint8_t var1;
    uint8_t var2;
} type1_t;

int __main(void)
{
        type1_t main_var;                
    
        main_var.var1    =    0xFF;        
        main_var.var2    =    0xFF;

    f1(&main_var);

}

void f1(type1_t *f1_var1)
{
    f1_var1->var1    >>=    1;

}

Go to the top of the page
 
+Quote Post
MySOL
сообщение May 11 2014, 14:13
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 67
Регистрация: 17-06-12
Пользователь №: 72 370



Цитата(Палыч @ May 11 2014, 17:55) *
Вы забыли свою структуру где либо разместить (выделить под неё память).

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


Цитата(kolobok0 @ May 11 2014, 18:00) *
ответ прозвучал уже, ну и ышо пять копеек: о выравнивании не забудьте. либо прямо в коде сохраняете старое, ставите прагмой новое,
после возвращаете старое. либо глобально на весь проект через ключики компиляции...

Простите, но я вас немного не понял. Если можете, ткните носом в статейку, где можно про это почитать, что бы вас не утруждать

Цитата(KnightIgor @ May 11 2014, 18:03) *
Код
typedef struct type1                          
{
    uint8_t var1;
    uint8_t var2;
} type1_t;

int __main(void)
{
        type1_t main_var;                
    
        main_var.var1    =    0xFF;        
        main_var.var2    =    0xFF;

    f1(&main_var);

}

void f1(type1_t *f1_var1)
{
    f1_var1->var1    >>=    1;

}

По-моему вы ошиблись=)
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение May 11 2014, 14:27
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



когда вы объявляется
my_str * str;

str - это указатель на структуру, на место в памяти где она лежит, но сам по себе указатель ничто, структуры нет.

my_str str;

так вы создадите структуру и сможете обращаться к ее полям как str.field, то есть через точку.

далее можно сделать указатель my_str *str2 = &str;
и уже обращаться к полям через стрелку
str2->field, при это такое обращение будет к полю именно первой структуры str.


структуры периферии проца описаны через указатели так (условно)

GPIO_STR *PORT1 = (GPIO_STR *) 0x434002300;
потому что в памяти уже есть данные лежащие как поля в структуре, это собственно регистры управляющие периферией, и вы создаете явный указатель на эту область памяти

Цитата
Простите, но я вас немного не понял. Если можете, ткните носом в статейку, где можно про это почитать, что бы вас не утруждать


есть разное выравнивание памяти, и иногда структура вида
struct...
{
char field1;
char field2;
}

может быть в памяти представлена 2 байтами, лежащими друг за другом, а может 8 байтами, где в 0 лежит field1, потом 3 байта пропуска, и в 4 лежит filed2. Это сделано потому что некоторые процы умеют брать данные только 32 битными или 16 битными словами, и в принципе не могут обращаться в области памяти с адресами не кратными их размеру слова.

так вот есть специальные слова позволяющие подсказывать как создавать структуру, типа __packed




Цитата
По-моему вы ошиблись=)


он не ошибся, он заменил указатель структуры на экземпляр

type1_t main_var;
вместо ваших
type1_t *main_var;

и соответственно вызовы через стрелку на вызовы через точку.

а также добавил функцию обработки данных структуры через указатель...

И в целом это все не относиться к кейлу или арму, это вообще вопросы базового знания языка С....
Go to the top of the page
 
+Quote Post
MySOL
сообщение May 11 2014, 16:55
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 67
Регистрация: 17-06-12
Пользователь №: 72 370



Цитата(Golikov A. @ May 11 2014, 18:27) *
....

Благодарю, что указали на ошибку при инициализации указателя!

Благодарю всех за помощь! Проблема решена

Сообщение отредактировал IgorKossak - May 12 2014, 09:02
Причина редактирования: бездумное цитирование
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение May 11 2014, 17:02
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Выравнивание - с этим ничего не сделаешь, с этим надо житьsm.gif..
вот на пальцах смысл.

берем проц типа кортекс м0, если не ошибаюсь этот процессор не умеет обращаться к памяти без выравнивания.

делаем в нем структуру
struct str
{
int8_t A;
int8_t B;
}
он выделяет 8 байт памяти и кладет данные
A
0
0
0
B
0
0
0

работаем внутри проца и все счастливы. Теперь мы добавляем какой-то интерфейс с внешним миром, например с PC или делаем сохранение параметров в память. Радостно делаем функцию которая посылает данные, с указателем на данные и размером данных, вызываем SaveSendData(MY_STR, 2) и что? облом, структура то не 2 а 8 байт, половина не сохранилась.

вызываем SaveSendData(MY_STR, sizeof(MY_STR)), все хорошо, но в памяти отъели 8 байт если мы про это не знаем может затереть данные.

Теперь на РС делаем ответную структуру
struct str{char A; char B} и что дальше? в компе то нет выравнивания, структура 2 байта, прямое копирования и пересылка - опять облом...


казалось, ок, если такая структура плохо, делаем ее

struct __packed str
{
int8_t A;
int8_t B;
}

пересылка - сохранение в память - прием на компе - супер! вот оно счастье, но!

Проц то не умеет обращаться в не выровненые адреса, и обращение my_str.B будет всегда вести в my_str.A, хоть убейся об него, пишите В, меняете А, читаете В, получаете А. И один способ записать или изменить В, это считать 32 бита A,B,0,0, вырезать маской нужную часть, сдвинуть и считать данные, для изменения обратно, считать 32 бита, масками изменить нужный кусок, записать обратно...

То есть либо теряем скорость, либо удобство, и об этом надо думать и понимать что у вас происходит....
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 11 2014, 18:17
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Не очень понял как мешает выравнивание структуре
struct str {
int8_t A;
int8_t B;
}
в ней-же все элементы - байт. На любом CPU, который умеет работать с байтами (и PC и Cortex-M0), с такой структурой никаких проблем выравнивания не будет.
Цитата(Golikov A. @ May 11 2014, 23:02) *
в компе то нет выравнивания

В компе-то - нет, но в си-компиляторах есть. Вне зависимости от CPU.
Насчёт пакованных структур - тоже не понял. Компиляторы (IAR во всяком случае) при работе с пакованными структурами на CPU не умеющем
невыровненный доступ, знают это прекрасно и выполняют доступ к членам структуры в соответствии с величиной пакованности (1,2,...) -
разбивают обращения на несколько 8-и или 16-и-битных (загляните в листинг!). И си-программисту эта кухня невидима. Скорость конечно будет ниже.
Но на удобство почти никак не повлияет. Единственно - будет проблема с указателями на такие структуры.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение May 11 2014, 18:49
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



да..., вот потому и хорошо даже для себя много раз прописывать даже очевидные вещи, я правда был не корректен и не точен

в структуре
struct
{
char A;
char B;
}
наверное, правда, проблем не будет, а в структуре
struct
{
char A;
char B;
int C;
}
проблемы точно должны быть. Также должны быть проблемы между 2 соседними структурами, в массиве, например, если думать что начало второй через sizeof(str) после начала первой....

Цитата
В компе-то - нет, но в си-компиляторах есть. Вне зависимости от CPU.

Тут я опять не совсем корректен. Я имел ввиду глобально, что обычно на компьютере в силу архитектуры их процов (блин сейчас правда и для компа процов уже не 1, но будем мыслить шире) обычно (по умолчанию) память пакована до байтовой границы. Опять же более строго для все обще принятых компиляторов и языков.

Естественно спец компиляторы под платформу с С язык скрывают всю эту кухню, и никогда написав в коде str.B, вы не измените и не получите соседнего поля, но за этим обращением может быть скрыто много действий, то есть как минимум оно может стать не атомарным. Сейчас процы все быстрее, и пару тактов туда суда погоды не делают, но не атомарность может здорово что-то загадить при наличии прерываний.
А в 32 битном микроблайзе попытка копирования или печати массива с 1, 2, 3 адреса всегда копировала или печатала его с 0, это не относится к упаковке, но относиться к выравниванию.
Иногда разбирая или наоборот заполняю структуру удобнее копировать ее не по полям, а большими кусками из других кусков, данных и памяти, и при таких операциях надо всегда четко знать что как лежит.

Мне кажется что кто пишет под процы, должен очень хорошо знать эту кухню изнутри, мы особая каста это не в виндус thread-ов наделать, а потом писать в форумах что программ без ошибок не бывает. И я пытался на примерах (возможно не очень корректно изложенных) показать с чем мы имеем дело.
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 11 2014, 19:20
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Golikov A. @ May 12 2014, 00:49) *
struct
{
char A;
char B;
int C;
}
проблемы точно должны быть. Также должны быть проблемы между 2 соседними структурами, в массиве, например, если думать что начало второй через sizeof(str) после начала первой....

В чём-же? rolleyes.gif
Ну разве, что если использовать её на разных системах, с разным размером int....
Вам известно, что в структурах (классах) си по умолчанию выполняется выравнивание (вне зависимости от CPU; это правило языка си)?
Ну только если конечно не предпринять спец. мер (pack).
Также и начало второй в массиве - всегда после sizeof() от начала первой как ни странно... rolleyes.gif
Размер (sizeof()) также выравнивается на размер выравнивания структуры (который в свою очередь равен размеру максимального члена).
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение May 11 2014, 20:55
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



о том вроде и беседуем...

Вы уверены что все проекты что вы создаете в кейле или других средах, под разные процы по умолчанию упакованы до байта, перефразирую, уверены что нигде не задается метод пакования отличный от побайтно?

А вы уверены что упакованные 6 байтные структуры идут в памяти через 6 байт на всех типах процов?

Go to the top of the page
 
+Quote Post
jcxz
сообщение May 12 2014, 03:56
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Хм... Я разве где-то подобное говорил??
Я вообще-то говорил почти противоположное:
1. Структуры в си по умолчанию не упакованные.
2. Выравнивание структуры равно выравниванию максимального члена структуры.
3. Максимальное выравнивание для встроенных типов данных как правило не превышает основной разрядности CPU (хотя это не могу утверждать с полной уверенностью).
(т.е. - если CPU 32-разрядный, то выравнивание 64-битного встроенного типа будет всё равно ==32).

Про упакованность - тоже Вы что-то не поняли. Я как раз писал, что пакование может выполняться не обязательно до уровня байт, может быть до уровня 16-бит или др.
см. #pragma pack(push, N) в IAR к примеру. Пример IAR:
#pragma pack(push, 2)
struct T {
u32 a;
u8 b;
};
#pragma pack(pop)
В данной структуре будет sizeof(T)==6. И выравнивание её будет равно ==16бит.

И вообще - упаковка не входит в язык си и может выполняться по-разному на разных компиляторах.

Цитата(Golikov A. @ May 12 2014, 02:55) *
А вы уверены что упакованные 6 байтные структуры идут в памяти через 6 байт на всех типах процов?

Очевидно, что в си, если имеется структура (не важно - пакованная или нет), то в массиве элементов этой структуры начало каждого следующего элемента будет
находиться по смещению sizeof() от предыдущего. А вот уже величина этого sizeof(T) будет зависеть от наличия pack() в её атрибутах и величины пакования этого самого pack().
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение May 12 2014, 04:40
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Что-то я совсем потерялся....

Что в процах с 32 битным выравниванием данных прямые бездумные обращения к памяти чреваты - это точно. В таких процах создание массивов элементов размера не кратного 32 битам и бездумное обращение с ними как с памятью - тоже чревато.

А вот объяснения и примера я чет хорошего придумать не могу%(.... вы все врем меня стандартами языка придавливаетеsad.gif....
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 12 2014, 06:07
Сообщение #15


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Golikov A. @ May 12 2014, 07:40) *
А вот объяснения и примера я чет хорошего придумать не могу%(.... вы все врем меня стандартами языка придавливаетеsad.gif....
Объяснения чего? Чреватости? Пожалуйста: MSP430, 16-битный, доступ к 16-битному значению по невыровненному адресу игнорирует младший бит адреса, результат - идет обращение к одному байту переменной и одному сосенднему. ARM7TDMI - обычно аналогично. В Cortex-M0 - исключение HardFault. Cortex-M3 - Исключение UsageFault или нормальный доступ для некоторых инструкций в зависимости от бита UNALIGN_TRP, для остальных инструкций - UsageFault. Пример в первом же сообщении этой темы:

Код
void f1(uint16_t *f1_var1);

typedef struct type1                          
{
    uint8_t var1;
    uint8_t var2;
} type1_t;

...
    type1_t *main_var;                
    .....
    f1((uint16_t*)main_var);


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 07:52
Рейтинг@Mail.ru


Страница сгенерированна за 0.01558 секунд с 7
ELECTRONIX ©2004-2016