|
|
  |
Последовательное размещение переменных в памяти (IAR 6.4) |
|
|
|
Jan 5 2013, 19:08
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 28-11-07
Пользователь №: 32 772

|
Мне нужно записать содержимое нескольких массивов в EEPROM. Есть вариант скопировать сначала все в один буфер, а потом все одним блоком записать в EEPROM, но для этого нужно выделять много оперативки под буфер. Можно ли как нибудь сказать компилятору, что переменные должны располагаться в памяти последовательно?
Конструкции типа: #pragma location=0x20000000 __no_init mainServerTypeDef mainServer; #pragma location=0x20000000+sizeof(mainServer) __no_init devicesBuiltTypeDef devicesBuilt[DEVICES_BUILT_MAX]; #pragma location=0x20000000+sizeof(mainServer)+sizeof(devicesBuilt) __no_init devicesRFTypeDef devicesRF[DEVICES_RF_MAX];
не помогают. Копилятор в этой области размещает другие переменные. Можете что-нибудь посоветовать? Пишу под процессор stm32f207 и 24c128. Компилятор IAR 6.4
|
|
|
|
|
Jan 5 2013, 20:11
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(Boriska @ Jan 5 2013, 21:08)  Можно ли как нибудь сказать компилятору, что переменные должны располагаться в памяти последовательно? Возможно компилятор решил что переменные не нужны. Попробуйте такой вариант: Код #pragma location=0x20000000 __root __no_init mainServerTypeDef mainServer;
|
|
|
|
|
Jan 5 2013, 20:36
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(Boriska @ Jan 5 2013, 21:08)  Можно ли как нибудь сказать компилятору, что переменные должны располагаться в памяти последовательно? На уровне компилятора -- поместить их все в одну охватывающую структуру. Код struct { mainServerTypeDef mainServer; devicesBuiltTypeDef devicesBuilt[DEVICES_BUILT_MAX]; devicesRFTypeDef devicesRF[DEVICES_RF_MAX]; } cfg; Будут все вместе и в заданном порядке. Неудобство -- придётся обращаться как к полям структуры cfg. На уровне линкера -- помещать в исходниках все переменные такого рода в специальную секцию, её описать линкеру, он соберёт все в одну кучу. Как бонус можно располагать переменные в разных файлах, при включении файла в проект его часть подошьётся автоматически. Но порядок переменных не гарантирован. Для «одним блоком записть в EEPROM» нужно будет обращаться к определяемым линкером символам начала секции и размера секции.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jan 5 2013, 21:23
|
Гуру
     
Группа: Свой
Сообщений: 2 360
Регистрация: 6-03-06
Из: Кишинев
Пользователь №: 15 025

|
И еще не забудьте указать, что структура пакованная, иначе она может иметь вовсе не ту длину, на которую Вы рассчитываете. Что-то типа "pack", но я давно ИАР не использовал, смотрите в актуальной документации. Но учтите, что с пакованными структурами он дольше работает. Метод со структурой- самый лучший из возможных. Он универсален и легко подается модификации. Я в подобную структуру не только в ПЗУ данные собираю, но и ОЗУшные глобальные переменные тоже: очень удобно при отладке и любых разборках-модификациях. То есть каждый модуль объявляет свой тип структуры, а main.h имеет все эти подчиненные структуры как "подструктуры" в структуре GlobalValues, типа такого:
typedef struct { modbus_t modbus; AD7192_t ad7192; DATA_COLLECT_STR_TYPE DatCollect; LCD_Global_t lcd; Buzzer_t buzzer; }GlobalValues_t;
|
|
|
|
|
Jan 6 2013, 14:20
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 28-11-07
Пользователь №: 32 772

|
Цитата(_Артём_ @ Jan 6 2013, 00:11)  Возможно компилятор решил что переменные не нужны. Это проверил. Переменные создаются. Вот только компилятор проверяет пересечение переменных, которые идут с директивой location, а остальные пихает, не обращая на занятую область никакого внимания. Цитата(ReAl @ Jan 6 2013, 00:36)  На уровне компилятора -- поместить их все в одну охватывающую структуру. Спасибо за идею. У меня была такая мысль. Не понравилось наличие дополнительного префикса. Ну если говорите, что нужно делать так, придется делать так  Цитата(Ruslan1 @ Jan 6 2013, 01:23)  И еще не забудьте указать, что структура пакованная, иначе она может иметь вовсе не ту длину, на которую Вы рассчитываете. Что-то типа "pack", но я давно ИАР не использовал, смотрите в актуальной документации. А что такое пакованная? pragma pack - выравнивание? Сейчас длина именно такая, как я прошу. В каком случае компилятор решит ее уменьшить? Или он может за счет выравнивания каждый раз вставлять разное число "пробелов" между элементами структуры?
|
|
|
|
|
Jan 6 2013, 15:08
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 28-11-07
Пользователь №: 32 772

|
Цитата(Ruslan1 @ Jan 6 2013, 18:36)  Т.е. sizeof() вернет размер без учета выравнивания? Если так, то я понял о чем Вы сказали.
|
|
|
|
|
Jan 6 2013, 15:17
|
Гуру
     
Группа: Свой
Сообщений: 2 360
Регистрация: 6-03-06
Из: Кишинев
Пользователь №: 15 025

|
Цитата(Boriska @ Jan 6 2013, 17:08)  Т.е. sizeof() вернет размер без учета выравнивания? Если так, то я понял о чем Вы сказали. нет. sizeof всегда вернет тот размер, который реально занимает структура, это общее количество занимаемых структурой байт в ОЗУ а не "полезное" количество байтов, занимаемых переменными. Если структура выровнена по 1 байту, то пропусков не будет. Если структура выравнена по 2 байта (16 бит) - то 1-байтная величина займет 2 байта. Пример typedef struct { u8 val1; u8 val2; u16 val3; }str_t; если структура выровнена по 1 байту: sizeof(str_t) = 1+1+2 = 4 если структура выровнена по 2 байта: sizeof(str_t) = 2+2+2 = 6 если структура выровнена по 4 байта: sizeof(str_t) = 4+4+4 = 12
|
|
|
|
|
Jan 6 2013, 15:27
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 28-11-07
Пользователь №: 32 772

|
Так зачем нужна упаковка? Или компилятор в образовавшиеся промежутки может пихать другие переменные?
|
|
|
|
|
Jan 6 2013, 20:09
|
Гуру
     
Группа: Свой
Сообщений: 2 360
Регистрация: 6-03-06
Из: Кишинев
Пользователь №: 15 025

|
Цитата(Boriska @ Jan 6 2013, 17:27)  Так зачем нужна упаковка? Или компилятор в образовавшиеся промежутки может пихать другие переменные? http://en.wikipedia.org/wiki/Data_structure_alignment(Пожалуйста, почитайте именно английский вариант этой статьи, а не русскую "аннотацию") Там же сказано зачем упаковка бывает нужна (ищите по термину "packed", если всю статью не одолеете) Я под упаковкой подразумеваю плотно сидящие в памяти переменные, друг-за дружкой, без пустот между ними. а, вот, нашел. оно не pack(), a __packed: http://netstorage.iar.com/SuppDB/Public/SU...Example%205.pdfЦитата оттуда: Код typedef unsigned char u8; typedef unsigned short int u16; //typedef __packed struct __packed struct Packed_Info { u8 Var8a; u16 Var16a; u8 Text[4]; }; u16 Length = sizeof(struct Packed_Info); ----------------------------------------------------- IAR assembler output: ----------------------------------------------------- 89 typedef unsigned char u8; 90 typedef unsigned short int u16; 91 92 __packed struct Packed_Info { 93 u8 Var8a; 94 u16 Var16a; 95 u8 Text[4]; 96 }; 97 \ In section .data, align 2 98 u16 Length = sizeof(struct Packed_Info); \ Length: \ 00000000 0700 DC16 7 то есть упаковали в 7 байт. Без упаковки по умолчанию было бы выравнено как процессору-компилятору удобно (скажем, если по 4 байта на переменную, то 24 байта на структуру).
|
|
|
|
|
Jan 7 2013, 10:49
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 28-11-07
Пользователь №: 32 772

|
Цитата(Ruslan1 @ Jan 7 2013, 00:09)  http://en.wikipedia.org/wiki/Data_structure_alignment(Пожалуйста, почитайте именно английский вариант этой статьи, а не русскую "аннотацию") Там же сказано зачем упаковка бывает нужна (ищите по термину "packed", если всю статью не одолеете) Я под упаковкой подразумеваю плотно сидящие в памяти переменные, друг-за дружкой, без пустот между ними. Нет, у меня есть общие представления что такое упаковка и выравнивание. Вопрос был "зачем она нужна в данном конкретном случае"? Сейчас проверил с разными режимами оптимизации: компилятор при выравнивании не использует отступы для хранения других переменных, похоже, упаковку можно не использовать. Просто у меня это наиболее используемые структуры и есть критические (по времени выполнения) секции где операции нужно выполнять как можно быстрее. Очень не хотелось бы тратить ресурсы на распаковку.
|
|
|
|
|
Jan 7 2013, 12:45
|
Гуру
     
Группа: Свой
Сообщений: 2 360
Регистрация: 6-03-06
Из: Кишинев
Пользователь №: 15 025

|
Цитата(Boriska @ Jan 7 2013, 12:49)  Нет, у меня есть общие представления что такое упаковка и выравнивание. Вопрос был "зачем она нужна в данном конкретном случае"? Сейчас проверил с разными режимами оптимизации: компилятор при выравнивании не использует отступы для хранения других переменных, похоже, упаковку можно не использовать. Просто у меня это наиболее используемые структуры и есть критические (по времени выполнения) секции где операции нужно выполнять как можно быстрее. Очень не хотелось бы тратить ресурсы на распаковку. Упаковка позволяет получить длину структуры, которая: 1. Имеет минимальную длину 2. Эта длина не зависит от типа компилятора или процессора (если типы определены пользователем, а не используется безликий "int" неизвестной длины). Например, если Вы хотите занять в ПЗУ область 256 байт (одна страница, или просто ПЗУ такого объема), и собственно данных у Вас 150 байт, то Вам очень не понравится, если реальная неупакованная структура, содержащая 150 байт данных, будет иметь длину 300 байт или 600 байт, в зависимости от используемого процессора. (1) и (2) также очень полезны при передаче данных и обработке этой структуры на процессоре другой разрядности. Упакованные данные везде выглядят одинаково, а непакованные- нет. Если Вас все это не интересует, а также ОЗУ достаточно- то пользуйтесь непакованной структурой, такой вид оптимален для скорости доступа к данным в ОЗУ.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|