секции кода и размещение в памяти
язык: С99
IDE: Eclipse
Подскажите, пожалуйста, как заставить линковщик разместить переменную в определенной секции кода(что-то подобное типа .bss, .data).
В GCC есть аттрибут "section".
1. Как с данным атрибутом работать под windows?
2. Как указать линковщику адресс начала данной секции и его размер (Что будет если стандартная секция налезет на пользовательскую
и можно ли этого избежать)?
3. Как сделать чтоб функция принимала параметры размещенные в пользовательской секции и тип параметра проверялся на этапе компиляции
(в идеале сделать проверку выхода за пределы области)?
4. Как писать и читать из данной секции?
Хочу сделать чтоб исходник для устройства с "Гарвардской" архитектурой мог спокойно выполняться на архитектуре "фон Неймана".
Заранее извиняюсь, если немного попутал термины.
Код:
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);
}
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);
}
Тут самое главное от какого контроллера плясать с бубнами.
Мало ключевых слов нахватались, нада расширять словарный запас, но смысл в их наборе все равно не появится.
контроллера предоставляет специальные функции. Я хочу код устройства запустить на ПК (само собой перекомпилировав его), а функции которые работают с памятью отличной от ОЗУ, будут только эмитировать свою работу, а реально должны работать с переменными размещенными в определенном месте памяти. Но при этом компилятор должен все же отличать переменные объявленные в простой памяти и в "пользовательской" секции.
Код:
uint8_t var1; //ОЗУ
uint8_t var2 EEMEM; //EEPROM
//функции принимающие разные типы параметров
void func(uint8_t param1){}
void func_EE(uint8_t param2){
//....
//работа с переменной в EEPROM
}
uint8_t var2 EEMEM; //EEPROM
//функции принимающие разные типы параметров
void func(uint8_t param1){}
void func_EE(uint8_t param2){
//....
//работа с переменной в EEPROM
}
Цитата: Suleyman
Попробую лучше объяснить. Например есть энергонезависимая память (для краткости EEMEM). Для того чтобы с ней работать, производитель
контроллера предоставляет специальные функции. Я хочу код устройства запустить на ПК (само собой перекомпилировав его), а функции которые работают с памятью отличной от ОЗУ, будут только эмитировать свою работу, а реально должны работать с переменными размещенными в определенном месте памяти. Но при этом компилятор должен все же отличать переменные объявленные в простой памяти и в "пользовательской" секции.
контроллера предоставляет специальные функции. Я хочу код устройства запустить на ПК (само собой перекомпилировав его), а функции которые работают с памятью отличной от ОЗУ, будут только эмитировать свою работу, а реально должны работать с переменными размещенными в определенном месте памяти. Но при этом компилятор должен все же отличать переменные объявленные в простой памяти и в "пользовательской" секции.
Код:
uint8_t var1; //ОЗУ
uint8_t var2 EEMEM; //EEPROM
//функции принимающие разные типы параметров
void func(uint8_t param1){}
void func_EE(uint8_t param2){
//....
//работа с переменной в EEPROM
}
uint8_t var2 EEMEM; //EEPROM
//функции принимающие разные типы параметров
void func(uint8_t param1){}
void func_EE(uint8_t param2){
//....
//работа с переменной в EEPROM
}
Собственно и зачем здесь еще одна секция и условие, что "компилятор должен все же отличать переменные объявленные в простой памяти и в "пользовательской" секции"?
Цитата: Ramon
Собственно и зачем здесь еще одна секция и условие, что "компилятор должен все же отличать переменные объявленные в простой памяти и в "пользовательской" секции"?
Более правильный пример будет если функции принимают параметром указатель.
Код:
void func(uint8_t* param1){
uint8_t var = *param1;
}
void func_EE(uint8_t* param2){
uint8_t var = eeprom_read_byte(param2);
//.....
}
uint8_t var = *param1;
}
void func_EE(uint8_t* param2){
uint8_t var = eeprom_read_byte(param2);
//.....
}
Ваша подсказка именно то что нужно. Попробовал на тестовом коде:
Код:
#define USER_SECTION __attribute__((section("usersect")))
int var1 = 1;
int var2 USER_SECTION = 2;
int main(void) {
//.....
}
int var1 = 1;
int var2 USER_SECTION = 2;
int main(void) {
//.....
}
А можно, во время выполнения, каким-либо образом узнать начальный адрес секции и её размер чтоб по нему определить корректность полученной переменной?
Код:
Код:
struct thing *SetAddress = &__start_usersect;
for ( ; SetAddress < &__stop_usersect; ++SetAddress) {
/* что-то делаем с *SetAddress */
}
struct thing *SetAddress = &__start_usersect;
for ( ; SetAddress < &__stop_usersect; ++SetAddress) {
/* что-то делаем с *SetAddress */
}
Спасибо большое. Оба ваших ответа очень выручили.