реклама на сайте
подробности

 
 
> Проблемы перевода программы из IAR в WinAVR.
Oleg_IT
сообщение Nov 19 2007, 09:03
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 922
Регистрация: 3-06-05
Из: Москва
Пользователь №: 5 709



Проблема размещения массивов.
Есть такой текст в IAR, работает:

typedef struct FONT_DEF
{
unsigned char *au8FontTable; /* Font table start address in memory */
} FONT_DEF;

__flash unsigned char Font_1[] = {
7, 8, 0, 255
0x00,0x00,0x00,0x00,0x00,0x00,0x00,
……………………………………………..
0x98,0x64,0x24,0x24,0xFC,0x00,0x00
};

__flash unsigned char Font_2[] = {
5, 6, 32, 59
0x00,0x00,0x00,0x00,0x00,
………………………………………
0x24,0x1A,0x0A,0x3E,0x00
};

struct const FONT_DEF Font_TAB[] =
{
{
Font_1
},
{
Font_2
}
};

Перевожу его в WinAVR, получается так:

typedef struct FONT_DEF
{
unsigned char *au8FontTable; /* Font table start address in memory */
} FONT_DEF;

unsigned char Font_1[] __attribute__((__progmem__)) = {
7, 8, 0, 255
0x00,0x00,0x00,0x00,0x00,0x00,0x00,
……………………………………………..
0x98,0x64,0x24,0x24,0xFC,0x00,0x00
};

unsigned char Font_2[] __attribute__((__progmem__)) = {
5, 6, 32, 59
0x00,0x00,0x00,0x00,0x00,
………………………………………
0x24,0x1A,0x0A,0x3E,0x00
};

struct FONT_DEF Font_TAB[] =
{
{
Font_1
},
{
Font_2
}
};

Компилится, но не работает. В отладчики видно, что адреса рассчитываются не правильно. Реальный адрес массива Font_1 в progmem 0x2A, а в структуре Font_TAB он 0x54. Откуда такое смещение? Может я не правильно атрибуты задаю? Помогите разобраться.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 8)
KRS
сообщение Nov 19 2007, 09:55
Сообщение #2


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(Oleg_IT @ Nov 19 2007, 12:03) *
Компилится, но не работает. В отладчики видно, что адреса рассчитываются не правильно. Реальный адрес массива Font_1 в progmem 0x2A, а в структуре Font_TAB он 0x54. Откуда такое смещение? Может я не правильно атрибуты задаю? Помогите разобраться.

Так у атмела адресация флеша по словам, но если читать данные через Z то по байтам поэтому реальный адрес 0x2a (в словах) а для указателя на данные 0x2a*2 = 0x54
Go to the top of the page
 
+Quote Post
Oleg_IT
сообщение Nov 19 2007, 11:34
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 922
Регистрация: 3-06-05
Из: Москва
Пользователь №: 5 709



Цитата(KRS @ Nov 19 2007, 12:55) *
Так у атмела адресация флеша по словам, но если читать данные через Z то по байтам поэтому реальный адрес 0x2a (в словах) а для указателя на данные 0x2a*2 = 0x54

А что нужно сделать, что бы правильно было? Я же на процесс присвоения адресов при компиляции повлиять не могу.
Go to the top of the page
 
+Quote Post
GDI
сообщение Nov 19 2007, 12:21
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



Может ничего и не надо тут делать и затык не в адресах? Я конечно не дока в GCC, но вроде как там надо пользоваться функциями get_flash или что то вроде этого при работе с данными в памяти программ, т.е. простое присваивание как в ИАРе не будет работать.


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 19 2007, 12:28
Сообщение #5


Гуру
******

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



Цитата(Oleg_IT @ Nov 19 2007, 11:03) *
Есть такой текст в IAR, работает:
Совершенно непонятно как оно у вас работает в IAR. Вы указатель на ОЗУ инициализируете адресом объекта, находящегося во флеш. Если бы было unsigned char __flash *au8FontTable; то работало бы. В WinAVR есть файл pgmspace.h, он описан в документации на avr-libc. Там определен атрибут PROGMEM, чем-то похожий на __flash ИАРа. Вам надо использовать определенный там тип prog_char и функцию pgm_read_byte(). Увы, непосредственно запись var = *pgm_ptr не работает, вместо чтения из флеш генерится чтение из ОЗУ по тому же адресу, но самое неприятное - не генерится сообщения об ошибке или хотя бы предупреждения. Так что будьте внимательны.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Oleg_IT
сообщение Nov 19 2007, 13:44
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 922
Регистрация: 3-06-05
Из: Москва
Пользователь №: 5 709



Цитата(Сергей Борщ @ Nov 19 2007, 15:28) *
Совершенно непонятно как оно у вас работает в IAR. Вы указатель на ОЗУ инициализируете адресом объекта, находящегося во флеш. Если бы было unsigned char __flash *au8FontTable; то работало бы. В WinAVR есть файл pgmspace.h, он описан в документации на avr-libc. Там определен атрибут PROGMEM, чем-то похожий на __flash ИАРа. Вам надо использовать определенный там тип prog_char и функцию pgm_read_byte(). Увы, непосредственно запись var = *pgm_ptr не работает, вместо чтения из флеш генерится чтение из ОЗУ по тому же адресу, но самое неприятное - не генерится сообщения об ошибке или хотя бы предупреждения. Так что будьте внимательны.

В IAR, как не странно работает, и правильно.
Можно пример дать, как в WinAVR задавать массив массивов, которые находятся в памяти кода.
Атрибут __progmem__ у меня стоит, и в отладчике я вижу этот массив во флеше (надеюсь отладчик правильно показывает). А компилятор, в IAR так, не знаю как в GCC, разбирается какая переменная в какой памяти расположена и генерит соответствующий код.
Вопрос то мой не в доступе к памяти, а в смещении. Программа считывает правильно, но не по тому адресу!
Go to the top of the page
 
+Quote Post
bloodden
сообщение Nov 19 2007, 13:54
Сообщение #7


Бывалый
***

Группа: Validating
Сообщений: 375
Регистрация: 19-10-05
Из: Kiev, UA
Пользователь №: 9 853



Я с таким сталкивался. Указатель действительно указывал на адрес байта, а флеш адресуется словами. Проблему решил умножением на 2 smile.gif


--------------------
Заходите кому надо на мой сайт
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 19 2007, 16:01
Сообщение #8


Гуру
******

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



Цитата(Oleg_IT @ Nov 19 2007, 15:44) *
В IAR, как не странно работает, и правильно.
Какое "работает" - оно компилиться не должно. Могу предположить, что у вас где-то стоит галочка (если такая есть) "делать указатели generic по умолчанию". Но это дикий оверхед.
Цитата(Oleg_IT @ Nov 19 2007, 15:44) *
Можно пример дать, как в WinAVR задавать массив массивов, которые находятся в памяти кода.
что-то типа такого:
Код
typedef struct FONT_DEF
{
    prog_uint8_t *au8FontTable;
} FONT_DEF;


unsigned char Font_1[] __attribute__((__progmem__)) =
{
    5, 6, 32, 59,
};
PROGMEM FONT_DEF const Font_TAB[] =
{
    {
        Font_1
    },
};

uint8_t test(uint8_t font, uint8_t element)
{
    prog_char *pFont = (prog_char *)pgm_read_word(&Font_TAB[font]);
    uint8_t Byte = pgm_read_byte(&pFont[element]);
    return Byte;
}
Цитата(Oleg_IT @ Nov 19 2007, 15:44) *
Атрибут __progmem__ у меня стоит, и в отладчике я вижу этот массив во флеше (надеюсь отладчик правильно показывает). А компилятор, в IAR так, не знаю как в GCC, разбирается какая переменная в какой памяти расположена и генерит соответствующий код.
А вот в GCC пока нет. К сожалению, пока что компилятор не разбирается и без явного вызова inline-функций pgm_read_xxxxx() читает из ОЗУ. При использовании этих функций никаких преобразований адреса делать не нужно. Дело в том, что для команды LPM адрес слова хранится в битах 15...1, а адрес байта - в нулевом бите. А если рассматривать содержимое Z как 16-битное число, то получится нормальный байтовый адрес. Преобразование надо делать только в одном случае - при вызове функции по явному адресу. Тогда адрес располагается в битах 16...0 и байтовый адрес приходится делить на два.
Цитата(Oleg_IT @ Nov 19 2007, 15:44) *
Вопрос то мой не в доступе к памяти, а в смещении. Программа считывает правильно, но не по тому адресу!
Боюсь, вы ошибаетесь. Какой командой в дизассемблере программа у вас считывает значение?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Oleg_IT
сообщение Nov 20 2007, 09:41
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 922
Регистрация: 3-06-05
Из: Москва
Пользователь №: 5 709



Цитата(Сергей Борщ @ Nov 19 2007, 19:01) *
Какое "работает" - оно компилиться не должно. Могу предположить, что у вас где-то стоит галочка

- но работает же!!!! Про галочку не знаю, не смотрел.
Спасибо, разобрался, pgm_read_byte_near(…) помогло.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 17:59
Рейтинг@Mail.ru


Страница сгенерированна за 0.01454 секунд с 7
ELECTRONIX ©2004-2016