Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: 6480
Последний выпуск: 19.06.2015

секции кода и размещение в памяти

17K
16 ноября 2014 года
Suleyman
12 / / 15.06.2008
компилятор: порт gcc 4.8.1 под windows - MinGW.
язык: С99
IDE: Eclipse

Подскажите, пожалуйста, как заставить линковщик разместить переменную в определенной секции кода(что-то подобное типа .bss, .data).
В GCC есть аттрибут "section".
1. Как с данным атрибутом работать под windows?
2. Как указать линковщику адресс начала данной секции и его размер (Что будет если стандартная секция налезет на пользовательскую
и можно ли этого избежать)?
3. Как сделать чтоб функция принимала параметры размещенные в пользовательской секции и тип параметра проверялся на этапе компиляции
(в идеале сделать проверку выхода за пределы области)?
4. Как писать и читать из данной секции?

Хочу сделать чтоб исходник для устройства с "Гарвардской" архитектурой мог спокойно выполняться на архитектуре "фон Неймана".
Заранее извиняюсь, если немного попутал термины.
317
17 ноября 2014 года
UserNet2008
744 / / 03.04.2010
Код:
struct duart a __attribute__ ((section ("DUART_A"))) = { 0 };
          struct duart b __attribute__ ((section ("DUART_B"))) = { 0 };
          char stack[10000] __attribute__ ((section ("STACK"))) = { 0 };
          int init_data __attribute__ ((section ("INITDATA"))) = 0;
         
          main()
          {
            /* Initialize stack pointer */
            init_sp (stack + sizeof (stack));
         
            /* Initialize initialized data */
            memcpy (&init_data, &data, &edata - &data);
         
            /* Turn on the serial ports */
            init_duart (&a);
            init_duart (&b);
          }
источник
Тут самое главное от какого контроллера плясать с бубнами.
247
16 ноября 2014 года
Ramon
1.1K / / 16.08.2003
Мало ключевых слов нахватались, нада расширять словарный запас, но смысл в их наборе все равно не появится.
17K
16 ноября 2014 года
Suleyman
12 / / 15.06.2008
Попробую лучше объяснить. Например есть энергонезависимая память (для краткости EEMEM). Для того чтобы с ней работать, производитель
контроллера предоставляет специальные функции. Я хочу код устройства запустить на ПК (само собой перекомпилировав его), а функции которые работают с памятью отличной от ОЗУ, будут только эмитировать свою работу, а реально должны работать с переменными размещенными в определенном месте памяти. Но при этом компилятор должен все же отличать переменные объявленные в простой памяти и в "пользовательской" секции.


 
Код:
uint8_t var1;       //ОЗУ
uint8_t var2 EEMEM; //EEPROM

//функции принимающие разные типы параметров
void func(uint8_t param1){}
void func_EE(uint8_t param2){
    //....
    //работа с переменной в EEPROM
}
247
17 ноября 2014 года
Ramon
1.1K / / 16.08.2003
Цитата: Suleyman
Попробую лучше объяснить. Например есть энергонезависимая память (для краткости EEMEM). Для того чтобы с ней работать, производитель
контроллера предоставляет специальные функции. Я хочу код устройства запустить на ПК (само собой перекомпилировав его), а функции которые работают с памятью отличной от ОЗУ, будут только эмитировать свою работу, а реально должны работать с переменными размещенными в определенном месте памяти. Но при этом компилятор должен все же отличать переменные объявленные в простой памяти и в "пользовательской" секции.


 
Код:
uint8_t var1;       //ОЗУ
uint8_t var2 EEMEM; //EEPROM

//функции принимающие разные типы параметров
void func(uint8_t param1){}
void func_EE(uint8_t param2){
    //....
    //работа с переменной в EEPROM
}



Собственно и зачем здесь еще одна секция и условие, что "компилятор должен все же отличать переменные объявленные в простой памяти и в "пользовательской" секции"?

17K
17 ноября 2014 года
Suleyman
12 / / 15.06.2008
Всё это шаманство с памятью необходимо для эмуляции поведения алгоритма выполняемого на контроллере. Низкоуровневые функции работы с перифирией вынесены на абстрактный уровень и на момент разработки прошивки значение имеет только правильность выполнения логики алгоритма а не поведение линий ввода/вывода.

Цитата: Ramon

Собственно и зачем здесь еще одна секция и условие, что "компилятор должен все же отличать переменные объявленные в простой памяти и в "пользовательской" секции"?



Более правильный пример будет если функции принимают параметром указатель.

 
Код:
void func(uint8_t* param1){
 uint8_t var = *param1;
}
void func_EE(uint8_t* param2){
   uint8_t var = eeprom_read_byte(param2);
   //.....
}
Как видно из выше приведенного короткого примера, функции принимают одинаковый тип, но параметр для второй функции находится в EEPROM. И если по ошибке туда передать указатель на переменную в ОЗУ - компилятор спокойно это скомпилирует и не выдаст никакого предупреждения. Можно получить "баг" который придется очень долго искать или в худшем случае он уйдет в релизный продукт. На текущий момент у меня реализовано что все переменные находятся в ОЗУ, но хочется чтобы компилятор мог их как-то различать и по возможности выдавать предупреждение при компиляции или сигнализировать об ошибке во время выполнения. Но так как типы для компилятора в данный момент одинаковы - отловить ошибки нет возможности.
17K
17 ноября 2014 года
Suleyman
12 / / 15.06.2008
Большое спасибо, UserNet2008.
Ваша подсказка именно то что нужно. Попробовал на тестовом коде:

 
Код:
#define USER_SECTION __attribute__((section("usersect")))

int var1 = 1;
int var2 USER_SECTION = 2;


int main(void) {
  //.....
}
посмотрел в test.o - компилятор создал отдельную секцию


А можно, во время выполнения, каким-либо образом узнать начальный адрес секции и её размер чтоб по нему определить корректность полученной переменной?
317
18 ноября 2014 года
UserNet2008
744 / / 03.04.2010
Есть две переменные: __start_SECTION и __stop_SECTION . Используються для получения начальных и конечных адресов секции, например так:
 
Код:
Код:
struct thing *SetAddress = &__start_usersect;

for ( ; SetAddress < &__stop_usersect; ++SetAddress) {
    /* что-то делаем с *SetAddress */
}
17K
18 ноября 2014 года
Suleyman
12 / / 15.06.2008
Спасибо большое. Оба ваших ответа очень выручили.

Знаете кого-то, кто может ответить? Поделитесь с ним ссылкой.

Ваш ответ

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог