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

 
 
> Atmega1280 + внешняя SRAM (WinAVR 20070525), подключение внешнего ОЗУ
kurtis
сообщение May 13 2008, 16:43
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205



Возникло непреодолимое желание увеличить количество ОЗУ, с этой целью было подключено внешняя SRAM размером 64к.

Теперь пытаюсь обьяснить компилятору что у меня подключено внешнее ОЗУ:
1) Пишу в make-файле
Код
EXTMEMOPTS = -Wl,-Tdata=0x802200,--defsym=__heap_end=0x80ffff

адрес 0x802200 т.к. у нас atmega1280, а там 8к байт ОЗУ.

2) Далее читаю FAQ по avr-libc, одновременно передирая код ОТ СЮДА (ссылка)

Код
#include <avr/io.h>
/*
* place a function in the '.init1' section to enable external RAM so
* that the C runtime startup can initialize it during C startup.  
*/
void enable_external_ram (void) __attribute__ ((naked)) __attribute__ ((section (".init1")));

void enable_external_ram(void)
{
  /*
   * enable external memory, no wait states
   */
  MCUCR |= _BV(SRE);
}


После этих манипуляций, в теле программы я пишу следующий код
Код
int massiv[100][100];

void TTechnolog::Exec()
{
........
/*  Заполняем ОЗУ какими-то данными  */
    for(i=0;i<100;i++)
        for(j=0;j<100;j++)
            if(i%2)
                massiv[i][j]=0x55;
            else
                massiv[i][j]=0x11;
........

таким образом я добиваюсь того что у меня
Цитата
Size after:
main.elf :
section size addr
.data 192 8389120
.text 32744 0
.bss 24400 8389312
.stab 66576 0
.stabstr 26615 0
Total 150527
Т.е. получаем полностью заполненное внутренее ОЗУ, и немного заполненное внешнее (насколько я понимаю сам процесс). До всех манипуляций секция .bss была равна 4400 и мы получили ожидаемое приращение в размере в 20к байт!
Следовательно, ожидаю увидеть работающий процессор, но вместо этого он "висит"... Вероятность ошибки в других участках кода низка, т.к. когда я привожу файлы в исходное состояние, то плата полностью работает и весело моргает светодиодами!

В идеале хочется просто расширить адресное пространство ОЗУ без учета потери производительности из-за увеличения времени доступа к внешней памяти!

Для компиляции используется avr-c++, WinAVR 20070525.

Что я неправильно делаю???
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 6)
ReAl
сообщение May 13 2008, 17:01
Сообщение #2


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(kurtis @ May 13 2008, 19:43) *
1) Пишу в make-файле
Код
EXTMEMOPTS = -Wl,-Tdata=0x802200,--defsym=__heap_end=0x80ffff

адрес 0x802200 т.к. у нас atmega1280, а там 8к байт ОЗУ.
Ой что-то там такое было, что линкер знает процессоры в лицо (по -mmcu=... ) и подставляет для мег64/128/... адрес начала .data от себя, игнорируя линкерный скрипт, в котором по какой-то традиции начало осталось 0x800060 от меги103.
Может он и команду из командной строки игнорирует?
Посмотрите map-файл, что куда реально легло.

Цитата(kurtis @ May 13 2008, 19:43) *
таким образом я добиваюсь того что у меня
Т.е. получаем полностью заполненное внутренее ОЗУ
А стек небось как и раньше - инициализируется на конец внутреннего ОЗУ.
Попробуйте переопределить символ __stack верхушку внешнего ОЗУ.
Это посадит скорость вызовов/возвратов/push/pop и работы с локальными переменными, но по крайней мере будет ясно - в этом ли дело.

А вообще - может лучше поправить линкерный скрипт и что-то всесте со стеком для скорости оставить внутри, а что-то вытолкать наружу в созданные для этого секции .xdata/.xbss с ручным указанием секций?


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
kurtis
сообщение May 14 2008, 13:55
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205



Спасибо что откликнулись!=)

Проблема начала постепенно решатся, тупое передирание кода ни к чему хооршему не привело - бит SRE который отвечает за использование внешнего ОЗУ, находится не в MCUCR, как в AtMega128, а в регистре XMCRA !!!

Цитата(ReAl @ May 13 2008, 20:01) *
А вообще - может лучше поправить линкерный скрипт и что-то всесте со стеком для скорости оставить внутри, а что-то вытолкать наружу в созданные для этого секции .xdata/.xbss с ручным указанием секций?


а можно по подробнее про это, а то я в документации ничего о секции .xdata/.xbss ???
Go to the top of the page
 
+Quote Post
ReAl
сообщение May 18 2008, 21:04
Сообщение #4


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(kurtis @ May 14 2008, 16:55) *
а можно по подробнее про это, а то я в документации ничего о секции .xdata/.xbss ???
Я малость отвлёкся...
В документации ничего про них и нет.
Есть про то, как их _добавить_ :-)

Пришлось немного попинать один старый проект - тогда вроде бы всё работало (хотя дело давно было, я уж не помню, может я и вручную что-то допиливал), а сейчас шалить начало.
Переделал немного скрипт, как в темах
http://electronix.ru/forum/lofiversion/index.php/t46152.html
http://electronix.ru/forum/lofiversion/index.php/t44607.html
Сергей Борщ советовал, внёс в него изменения, которые за это время у avr-gcc появились в скриптах по умолчанию (KEEP в основном) - компилируется и по .map да дизассемблеру выглядит правдоподобно, самой платки под рукой нет, проверить не могу.

"Значит вот как дело было, наша славная кобыла" (С) песня "Конный спорт" из цикла "Спортлото"

имела на борту мегу162 и 32К ОЗУ в старшей половине адресного пространства.
Сейчас это собирается WinAVR-20060421, 20070525, 20071221 и выглядит так:
В линкерном скрипте добавлено и изменено по рекомендациям из указанных выше тем
Код
MEMORY
{
  text   (rx)   : ORIGIN = 0, LENGTH = 16K
  data   (rw!x) : ORIGIN = 0x800100, LENGTH = 1K
  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 512
/*  sections xdata and xbss */
  xdata  (rw!x) : ORIGIN = 0x808000, LENGTH = 32K
}


и дальше после описания .noinit вставлено
CODE
.data :
{
PROVIDE (__data_start = .);
*(.data)
*(.data*)
*(.rodata) /* We need to include .rodata here if gcc is used */
*(.rodata*) /* with -fdata-sections. */
*(.gnu.linkonce.d*)
. = ALIGN(2);
_edata = .;
PROVIDE (__data_end = .);
} > data AT > text
.bss :
{
PROVIDE (__bss_start = .);
*(.bss)
*(.bss*)
*(COMMON)
PROVIDE (__bss_end = .);
} > data
__data_load_start = LOADADDR(.data);
__data_load_end = __data_load_start + SIZEOF(.data);


/* Global data not cleared after reset. */
.noinit :
{
PROVIDE (__noinit_start = .);
*(.noinit*)
PROVIDE (__noinit_end = .);
_end = .;
} > data


.xdata :
{
PROVIDE (__xdata_start = .);
*(.xdata*)
. = ALIGN(2);
PROVIDE (__xdata_end = .);
} > xdata AT > text

__xdata_load_start = LOADADDR(.xdata);
__xdata_load_end = __xdata_load_start + SIZEOF(.xdata);

.xbss (NOLOAD) :
{
PROVIDE (__xbss_start = .);
*(.xbss)
PROVIDE (__xbss_end = .);
__heap_start = .; /* у меня этого не было, кучей не пользовался */
} > xdata
__heap_end = 0x80FFFF; /* аналогично */


Таким образом просто объявленные переменные и стек размещаются во внутреннем ОЗУ.
Специально помеченные и куча - снаружи.

Код
#define XDATA __attribute__((section(".xdata")))
#define XBSS __attribute__((section(".xbss")))

extern const prog_uint8_t __xdata_load_start, __xdata_load_end;
extern uint8_t __xdata_start, __xdata_end;

...

uint8_t XBSS tx_data_buf[MAX_TX_BUF_SIZE];
uint8_t XDATA test[] = { 1, 3, 5};

...

INIT_CODE(3)
{
    // XMEM interface - one sector, fastest access, bus-keepers enabled
    MCUCR = MCUCR_MEM_MODE;     // also LOW level INT0, INT1
    EMCUCR = EMCUCR_MEM_MODE;   // also fallng edge INT2
    SFIOR = SFIOR_XMEM_MODE;
    /* копирование образа .xbss из флеша во внешнее ОЗУ */
    uint8_t *px = &__xdata_start;
    const prog_uint8_t *pf = &__xdata_load_start;
    uint16_t len = &__xdata_end - &__xdata_start;
    while(len--) {
        *px++ = pgm_read_byte( pf);
        ++pf;
    }
}


INIT_CODE(3) - код, помещаемый в секцию .init3, см хвост темы
http://electronix.ru/forum/lofiversion/index.php/t42970.html

Можно и зануление .xbss сделать, но это долго и мне было не нужно - там были только массивы буферов, а управляющие структуры к ним
а) внутри
б) всё равно инициализировались вручную
У меня и .xdata не было, это только сейчас добавил для полноты.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
kurtis
сообщение May 23 2008, 08:33
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205



Большое спасибо, буду пробовать!!! smile.gif
Go to the top of the page
 
+Quote Post
kurtis
сообщение Jun 6 2008, 13:52
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205



Прошу прощения что поднимаю старую тему....

Решил сделать "зануление" секции .xbss , написал в main.cpp следующий код
Код
    uint8_t * xbss_clean;
    
    for ( xbss_clean = __xbss_start; xbss_clean < __xbss_end; xbss_clean++)
        *xbss_clean = 0x00;

но компилятор ругается, говорит что
Цитата
./src/Main.cpp:98: error: '__xbss_start' was not declared in this scope
./src/Main.cpp:98: error: '__xbss_end' was not declared in this scope

Как мне их правильно обьявить, чтоб компилятор не ругался???
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 6 2008, 15:06
Сообщение #7


Гуру
******

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



Цитата(kurtis @ Jun 6 2008, 16:52) *
Как мне их правильно обьявить, чтоб компилятор не ругался???
Код
    uint8_t * xbss_clean;
    extern uint8_t __xbss_start, __xbss_end;
    for ( xbss_clean = &__xbss_start; xbss_clean < &__xbss_end; xbss_clean++)
        *xbss_clean = 0x00;


--------------------
На любой вопрос даю любой ответ
"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

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

 


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


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