Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Указатели в PROGMEM
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
demiurg_spb
Народ! Есть вопрос по поводу указателей хранящихся в памяти данных.

Сейчас я использую макрос такого плана:

Код
#define pgm_read_ptr(address)           ((void*)pgm_read_word(address))


Но программа переваливает за 64К и гипотетически возможны проблемы.
Т.к. указатели на данные могут быть 3-х байтными.

Может кто-нибудь написал универсальный макрос - поделитесь информацией...

Ну или чтобы хоть warning или error на этапе компиляции выскакивал когда ptr>65535.
Предупрежден - значит вооружён!
aesok
Цитата(demiurg_spb @ Jul 7 2008, 12:18) *
Код
#define pgm_read_ptr(address)           ((void*)pgm_read_word(address))


Но программа переваливает за 64К и гипотетически возможны проблемы.
Т.к. указатели на данные могут быть 3-х байтными.


Все данные описанные с атрибутом progmem распологаются во флеш после таблицы векторов прерываний, и до кода программы. Пока общий размер таких переменных не привысит примерно 63КВ, никаких проблем не будет, будет достаточно старданторного 2-х байтового указателя.

Анатолий.
demiurg_spb
Спасибо за укрепление духа!
О компоновке данных в flash я знаю.
Хотелось на будущее соломки подстелитьwink.gif
Вдруг в будущем незаметно для себя данные перевалят границу 64К.

А как обстоят дела с указателями на процедуры?
Ведь они могут быть где угодно...
aesok
Цитата(demiurg_spb @ Jul 7 2008, 14:31) *
Спасибо за укрепление духа!
О компоновке данных в flash я знаю.
Хотелось на будущее соломки подстелитьwink.gif
Вдруг в будущем незаметно для себя данные перевалят границу 64К.


Тогда вы заментите что ваша программа перестала работать.
Если вам действительно нужно больше 63КБ констант, можете постотреть патч для avr-libc здесь
http://savannah.nongnu.org/patch/?6352

Цитата(demiurg_spb @ Jul 7 2008, 14:31) *
А как обстоят дела с указателями на процедуры?
Ведь они могут быть где угодно...


С указателями на функции проблем нет, даже для 256КБ контроллеров.

Анатолий.
demiurg_spb
Цитата(aesok @ Jul 7 2008, 14:44) *
С указателями на функции проблем нет, даже для 256КБ контроллеров.


Я не понимаю.
Если я храню в flash таблицу указателей на функции, которые расположены где угодно.
То такая таблица должна быть 3-х байтной.
То мой макрос не прочитает указатель так как надо...
aesok
Цитата(demiurg_spb @ Jul 7 2008, 14:55) *
Я не понимаю.
Если я храню в flash таблицу указателей на функции, которые расположены где угодно.
То такая таблица должна быть 3-х байтной.
То мой макрос не прочитает указатель так как надо...


Указатели всегда 2-х байтные, указатель на функцию, это указакль не на байт а на слово. Тоесть для нижних 128К достаточно 2х байт чтобы хранить указатель на 64K слов программной памяти.

Если функция расположенна выше 128КБ, то указатель на функцию, это указатель на инструкцию JMP расположенную в нижних 128КБ ( 64K слов).

Анатолий.
demiurg_spb
Ещё раз большое спасибо!
Всё для меня прояснилось!
ReAl
Цитата(demiurg_spb @ Jul 7 2008, 11:18) *
Сейчас я использую макрос такого плана:
Код
#define pgm_read_ptr(address)           ((void*)pgm_read_word(address))

Но программа переваливает за 64К и гипотетически возможны проблемы.
Т.к. указатели на данные могут быть 3-х байтными.
Может кто-нибудь написал универсальный макрос - поделитесь информацией...

pgmspace.h имеет и макросы pgm_read_word_far() и т.п. - для доступа через ELPM ко всей памяти кода.
Но в простом применении
Код
int PROGMEM fi =1;
int i;
i = pgm_read_word_far( &fi);
Указатель усекается до 16 бит и потом знаково расширяется до 32 бит, т.е. выходит кака. По ссылке от Анатолия лежит дополнение - функции str*_PF для работы с данными во всей флеш-памяти и макрос GET_FAR_ADDRESS(var)
Это работает корректно:
Код
    i = pgm_read_word_far( GET_FAR_ADDRESS(fi) ); // без '&' !!!

Одна беда - секция трамплинов (находящаяся в нижней памяти таблица jmp на те функции в верхней памяти, от которых брался адрес), о которой говорил Анатолий, в линкерном скрипте находится после секции констант.
Код
    *(.vectors)
    KEEP(*(.vectors))
    /* For data that needs to reside in the lower 64k of progmem.  */
    *(.progmem.gcc*)
    *(.progmem*)
     __trampolines_start = .;
    /* The jump trampolines for the 16-bit limited relocs will reside here.  */
    *(.trampolines)
    *(.trampolines*)
     __trampolines_end = .;
    /* For future tablejump instruction arrays for 3 byte pc devices.
       We don't relax jump/call instructions within these sections.  */
    *(.jumptables)
    *(.jumptables*)
    /* For code that needs to reside in the lower 128k progmem.  */
    *(.lowtext)
    *(.lowtext*)
     __ctors_start = .;
     *(.ctors)
     __ctors_end = .;
в результате чего при росте массивов констант трамплины вылетауют сверх 64 раньше и "указатель на функцию" в виде указателя на jmp тоже становится 3-байтовым. Т.е. при таких объёмах констант становится невозможным использовать указатели на функции.

Цитата(aesok @ Jul 7 2008, 13:44) *
С указателями на функции проблем нет, даже для 256КБ контроллеров.
Пока константы не вытолкают трамплины слишком высоко (впрочем, при этом будет сообщение об ошибке на взятие адреса функции).
Может, лучше сразу секции .trampolines и .lowtext* поместить перед .progmem*? "им нужнее"
К этому просится какой-то PROGMEM_FAR и секция .progmem_far, которая в линкерном скрипте сразу расположена после всего кода. Таким образом можно будет сразу выделять константные данные, обращение к которым через длинные указатели uint_farptr_t и функции _PF устраивает, а в PROGMEM размещать только то, к чему хочется обеспечить более быстрый доступ более короткими макросами pgm_read_*_near().
demiurg_spb
Дааа... Всё гораздо интереснее smile.gif
aesok
Цитата(ReAl @ Jul 8 2008, 10:58) *
в результате чего при росте массивов констант трамплины вылетауют сверх 64 раньше и "указатель на функцию" в виде указателя на jmp тоже становится 3-байтовым. Т.е. при таких объёмах констант становится невозможным использовать указатели на функции.


Нет проблем если секции .trampolines и .lowtext* окажутся во вторых 64КБ,
указатели на код это указатели на слово, нужно чтобы они были в нижних 128КБ.
А вот секция .progmem*, для того чтобы работали функции *_p, должна быть в
нижних 64КБ. Проблемы с .trampolines и .lowtext* возникнут когда размер
секции .progmem* приблизиться к 128 КБ.

Цитата(ReAl @ Jul 8 2008, 10:58) *
Может, лучше сразу секции .trampolines и .lowtext* поместить перед .progmem*? "им нужнее"

Нет .progmem* должна быть в нижних 64КБ, а .trampolines и .lowtext* в нижних 128КБ тоесть .trampolines и .lowtext* должны быть после .progmem*.

Цитата(ReAl @ Jul 8 2008, 10:58) *
К этому просится какой-то PROGMEM_FAR и секция .progmem_far, ...


Тут наши мнения совпадают, я с месяц назад в avr-libc-dev предлагал добавить
.progmem_far, принципе с этим согласились, но пока нет времени заняться этим
патчем.

Анатолий.
ReAl
Цитата(aesok @ Jul 8 2008, 17:18) *
Нет проблем если секции .trampolines и .lowtext* окажутся во вторых 64КБ, указатели на код это указатели на слово, нужно чтобы они были в нижних 128КБ.
А вот секция .progmem*, для того чтобы работали функции *_p, должна быть в
нижних 64КБ. Проблемы с .trampolines и .lowtext* возникнут когда размер
секции .progmem* приблизиться к 128 КБ.
Ой, да-да-да. Это я запутался. Конечно, проблемы с трамплинами будут после 128Кбайт (64Кслов - на этом я и споткнулся), секции менять местами нет смысла.
Обычный доступ только в пределах 64Кбайт (а lowtext и трамплинов на ещё 64 К врядли наберётся smile.gif).
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.