|
|
  |
Внедрение бинарных данных в код, Как прилинковать бинарник и обратиться к этим данным в AVR GCC |
|
|
|
Nov 27 2008, 15:17
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
Задумал разместить некие данные из внешнего файла внутри прошивки. Разобрался, как сгенерировать объектный файл, как его прилинковать. написано, что при этом " определяются 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) попытки приводить типы (указатель к целому) для последующего сравнения получаются еще более кривыми... хочется красоты и правильности. есть какие-то дельные советы по этой теме?
Сообщение отредактировал ARV - Nov 27 2008, 15:20
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Nov 27 2008, 17:07
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(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; \ }) Анатолий.
|
|
|
|
|
Nov 27 2008, 21:51
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(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 подсказал уже.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 9 2009, 15:10
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(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
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Sep 10 2009, 06:35
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(demiurg_spb @ Sep 9 2009, 19:10)  Этот макрос не работает, если попытаться взять адрес не константы, а элемента константного массива с переменным индексом. Нет не работает. И об этом честно написано в коментарии к макросу. Анатолий.
|
|
|
|
|
Jan 7 2012, 20:16
|
Группа: Участник
Сообщений: 13
Регистрация: 7-01-12
Из: г. Москва
Пользователь №: 69 212

|
Цитата(ARV @ Nov 27 2008, 19:17)  Задумал разместить некие данные из внешнего файла внутри прошивки. Разобрался, как сгенерировать объектный файл, как его прилинковать. Мучаюсь с этой же задачей. Сгенерировал объектный файл, но не удается прилинковать его. avr-gcc ругается "Error 1 avr architecture of input file `FW_cp26m.o' is incompatible with avr:51 output". Не могли бы Вы подсказать как правильно линковать его?
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|