Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Внедрение бинарных данных в код
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
ARV
Задумал разместить некие данные из внешнего файла внутри прошивки. Разобрался, как сгенерировать объектный файл, как его прилинковать. написано, что при этом "определяются 2 символа вида _binary_XXXX_bin_start и _binary_XXXX_bin_end" - ну, это, как я понимаю, все и так знают (кстати, оказалось, что написано неверно в доке! там говорится, что эти символы с подчеркиванием на конце, а на самом деле подчеркивания нет!). НО!
теперь вопрос: как правильно орагнизуется последующее обращение к этим внедренным данным?

допустим, я делаю так:
Код
#include <avr/pgmspace.h>
extern PROGMEM uint8_t _binary_XXXX_bin_start[];
extern PROGMEM uint8_t _binary_XXXX_bin_end[];

PGM_P ptr = (void*)&_binary_XXXX_bin_start;
while (ptr != (void*)&_binary_XXXX_bin_end){
   PORTB = pgm_read_byte(ptr);
   ptr++;
}

вроде бы работает (судя по листингу), но:
1. мне не нравится эта реализация (как-то криво все написано), да и ворнинги получаются... дескать, указатель сравнивается с целым...
2. не очень понятно, как правильно организовать указатель на внедренный блок, если его размер больше 64К (т.е. для pgm_read_byte_far)

попытки приводить типы (указатель к целому) для последующего сравнения получаются еще более кривыми... хочется красоты и правильности.

есть какие-то дельные советы по этой теме?
aesok
Цитата(ARV @ Nov 27 2008, 18:17) *
дельные советы по этой теме?


Ипользуйте макрос GET_FAR_ADDRESS

Код
/* GET_FAR_ADDRESS() macro

   This macro facilitates the obtention of a 32 bit "far" pointer (only 24 bits
   used) to data even passed the 64KB limit for the 16 bit ordinary pointer. It
   is similar to the '&' operator, with some limitations.

   Comments:

   - The overhead is minimal and it's mainly due to the 32 bit size operation.

   - 24 bit sizes guarantees the code compatibility for use in future devices.

   - hh8() is an undocumented feature but seems to give the third significant byte
     of a 32 bit data and accepts symbols, complementing the functionality of hi8()
     and lo8(). There is not an equivalent assembler function to get the high
     significant byte.

   - 'var' has to be resolved at linking time as an existing symbol, i.e, a simple
     type variable name, an array name (not an indexed element of the array, if the
     index is a constant the compiler does not complain but fails to get the address
     if optimization is enabled), a struct name or a struct field name, a function
     identifier, a linker defined identifier,...

   - The natural place for this macro should be the header avr/pgmspace.h and the
     name... pgm_get_far_address?

   - The returned value is the identifier's VMA (virtual memory address) determined
     by the linker and falls in the corresponding memory region. The AVR Harvard
     architecture requires non overlapping VMA areas for the multiple address spaces
     in the processor: Flash ROM, RAM, and EEPROM. Typical offset for this are
     0x00000000, 0x00800xx0, and 0x00810000 respectively, derived from the linker
     script used and linker options. The value returned can be seen then as a
     universal pointer.

*/

#define GET_FAR_ADDRESS(var)                          \
({                                                    \
    uint_farptr_t tmp;                                \
                                                      \
    __asm__ __volatile__(                             \
                                                      \
            "ldi    %A0, lo8(%1)"           "\n\t"    \
            "ldi    %B0, hi8(%1)"           "\n\t"    \
            "ldi    %C0, hh8(%1)"           "\n\t"    \
            "clr    %D0"                    "\n\t"    \
        :                                             \
            "=d" (tmp)                                \
        :                                             \
            "p"  (&(var))                             \
    );                                                \
    tmp;                                              \
})


Анатолий.
Сергей Борщ
Цитата(ARV @ Nov 27 2008, 17:17) *
1. мне не нравится эта реализация (как-то криво все написано), да и ворнинги получаются... дескать, указатель сравнивается с целым...

А если так:
Код
#include <avr/pgmspace.h>
extern prog_char const _binary_XXXX_bin_start;
extern prog_char const _binary_XXXX_bin_end;

PGM_P ptr = &_binary_XXXX_bin_start;
while (ptr != &_binary_XXXX_bin_end){
   PORTB = pgm_read_byte(ptr);
   ptr++;
}
или так:
Код
#include <avr/pgmspace.h>
extern prog_char const _binary_XXXX_bin_start[];
extern prog_char const _binary_XXXX_bin_end[];

PGM_P ptr = _binary_XXXX_bin_start;
while (ptr != _binary_XXXX_bin_end){
   PORTB = pgm_read_byte(ptr);
   ptr++;
}
или так:
Код
#include <avr/pgmspace.h>
extern prog_char const _binary_XXXX_bin_start[];
extern prog_char const _binary_XXXX_bin_end[];

PGM_P ptr = &_binary_XXXX_bin_start[0];
while (ptr != &_binary_XXXX_bin_end[0]){
   PORTB = pgm_read_byte(ptr);
   ptr++;
}


Ну а если вместе со вторым вопросом, то aesok подсказал уже.
ARV
гм... 3 варианта... по-моему, непринципиально отличающиеся... но спасибо, буду пробовать.
demiurg_spb
Цитата(aesok @ Nov 27 2008, 21:07) *
Ипользуйте макрос GET_FAR_ADDRESS
Анатолий.
Этот макрос не работает, если попытаться взять адрес не константы, а элемента константного массива с переменным индексом.
Получается вот такой вот листинг. Прошу совета. Спасибо!
Код
float  k_popr = pgm_read_float_far( GET_FAR_ADDRESS(cs_k_voltage_popr[ ADE7753_Gains[1] ]));

634 002e E92C          mov r14,r9
635 0030 FF24          clr r15
636 0032 EE0C          lsl r14
637 0034 FF1C          rol r15
638 0036 EE0C          lsl r14
639 0038 FF1C          rol r15
640 003a 9701          movw r18,r14
641 003c 2050          subi r18,lo8(-(cs_k_voltage_popr))
642 003e 3040          sbci r19,hi8(-(cs_k_voltage_popr))
643 0040 D901          movw r26,r18

646 0042 20E0          ldi    r18, lo8(r26)                                 << Вот тут бяка.
647 0044 30E0          ldi    r19, hi8(r26)                                 <<
648 0046 40E0          ldi    r20, hh8(r26)                                 <<
649 0048 5527          clr    r21

657 004a 4BBF          out 59, r20
658 004c F901          movw r30, r18
659 004e 2791          elpm r18, Z+
660 0050 3791          elpm r19, Z+
661 0052 4791          elpm r20, Z+
662 0054 5691          elpm r21, Z
avr-gcc (WinAVR 20090313) 4.3.2
aesok
Цитата(demiurg_spb @ Sep 9 2009, 19:10) *
Этот макрос не работает, если попытаться взять адрес не константы, а элемента константного массива с переменным индексом.


Нет не работает. И об этом честно написано в коментарии к макросу.

Анатолий.
Jeca
Цитата(ARV @ Nov 27 2008, 19:17) *
Задумал разместить некие данные из внешнего файла внутри прошивки. Разобрался, как сгенерировать объектный файл, как его прилинковать.


Мучаюсь с этой же задачей. Сгенерировал объектный файл, но не удается прилинковать его. avr-gcc ругается "Error 1 avr architecture of input file `FW_cp26m.o' is incompatible with avr:51 output". Не могли бы Вы подсказать как правильно линковать его?
demiurg_spb
У вас задача иного рода. ТС хотел именно бинарные данные вкрячить, а вы объектный файл прилинковать хотите.
Возникает вопрос чем вы сбилдили объектник и для чего?
У вас там не только данные но и функции какие-либо имеются?
Сергей Борщ
QUOTE (demiurg_spb @ Feb 1 2012, 11:57) *
У вас задача иного рода.
Это кросспост. Проблему он давно решил: http://electronix.ru/forum/index.php?s=&am...t&p=1014019
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.