Перейти к содержанию
    

Здравствуйте. У меня проблема с внешней памятью при работе с АтМега64.

Есть программа, рабочая. При подключении внешней памяти начинаются непонятные ошибки, причем ошибки начинаются при выполнении команды memmove() или при выполнении функции вывода строки:

while (*s) ce210_send(*s++);

Вот строчка в мейкфайле, где включаю память, и потом флаги:

EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x8090ff
   ASFLAGS = -Wa,-ahlms=$(<:%.S=lst/%.lst),-gstabs -mmcu=$(MCU)
   CPFLAGS = -MMD -g -O$(OPT) -funsigned-char -funsigned-bitfields -fpack-struct -Wall -Wstrict-prototypes -Wa,-ahlms=$(<:%.c=lst/%.lst) -mmcu=$(MCU) $(CDEFS)
   LDFLAGS = -Wl,-Map=lst/$(TRG).map,--cref, -L$(LIBDIR), $(EXTMEMOPTS) -lm -mmcu=$(MCU)

Вот инициализация в программе:

    setreg(MCUCR, SRE, 1);    // enable external memory (xram)
   setreg(MCUCR, SRW10, 1);                      // configure xram
   XMCRA = _BV(SRW00) | _BV(SRW01) | _BV(SRW11); //

Видно, что проблемы именно с памятью, но вот только где конкретно, не могу понять.

Что не так?

P.S. Версия ВинАВР последняя.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте. У меня проблема с внешней памятью при работе с АтМега64.

Есть программа, рабочая. При подключении внешней памяти начинаются непонятные ошибки, причем ошибки начинаются при выполнении команды memmove() или при выполнении функции вывода строки:

while (*s) ce210_send(*s++);

 

А каким образом у вас "s" объявлена и инициализирована?

 

И потом, если s - указатель на массив, то надо смотреть приоритет операторов, может лучше пока написать так:

while (*s) 
{
   ce210_send(*s);
   s++;
}

 

Про приоритет операторов можно посмотреть тут:

http://cclib.nsu.ru/projects/gnudocs/texts/bogatir/9.html

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А каким образом у вас "s" объявлена и инициализирована?

 

void ce210_print(char *s)
{
   while (*s) ce210_send(*s++);
}

Я совершенно уверен, что дело тут не в приоритетах, как я уже сказал, без внешней памяти все работает правильно.

 

Да, еще одно наблюдение. При инициализации всей памяти, которая учавствует в memmove(), ошибки вроде исчезают. Шаманство какое-то...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возможно проблема в __heap_end=0x8090ff

 

как я понял, объем Вашей внешней памяти = 32k:

90ffH - 1100H = 7fffH = 32767 с учетом нулевого адреса 32768

 

У AVRа адресация ОЗУ начинается с адреса 0, следовательно при подключении внешней памяти объемом 32к адреса с 0x0000 по 0x10ff будут адресоваться как внутренние, а конец памяти будет = 0x7fff а не 0x90ff. Если Ваш указатель попадал на область выше 0x7fff то обращение шло в никуда, оттуда и могли возникать ошибки.

 

Это замечание справедливо если у вас нет конвертора адреса, который Ваш 0x1100 на шине адреса AVR преобрезует в 0x0000 на шине адреса ОЗУ.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет, не в этом дело :(

Да и не мог указатель так далеко забраться, я памяти мало использую.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет, не в этом дело :(

Да и не мог указатель так далеко забраться, я памяти мало использую.

 

Вы не ответили на вопрос: каким образом у вас "s" объявлена и инициализирована?

 

Какую внешнюю память вы используете?

 

Кстати, я в своем проекте (правда, у меня ATmega128), вообще никаких

-Tdata=0x801100,--defsym=__heap_end=0x8090ff не использую, все без этого великолепно работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы не ответили на вопрос: каким образом у вас "s" объявлена и инициализирована?

 

Я ответил.

void ce210_print(char *s)

{

while (*s) ce210_send(*s++);

}

это вся функция.

 

Какую внешнюю память вы используете?

Samsung 328А

Кстати, я в своем проекте (правда, у меня ATmega128), вообще никаких

-Tdata=0x801100,--defsym=__heap_end=0x8090ff не использую, все без этого великолепно работает.

Попробую так...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы не ответили на вопрос: каким образом у вас "s" объявлена и инициализирована?

 

Я ответил.

void ce210_print(char *s)

{

while (*s) ce210_send(*s++);

}

это вся функция.

 

Я понимаю, что это вся функция :-) Вы в неё в качестве параметра передаете указатель, который объявлен и инициализирован у вас где-то в основной программе или в другой функции. Про объявление и инициализацию этого указателя я у вас и спрашивал.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

так:

ce210_print("string");

или так:

char* a;

ce210_print(a);

 

А с чего вы решили, что данные переменные будут размещены во внешней памяти?

Кстати, во втором случае, я не вижу инициализации указателя.

Вот, например, если бы вы написали:

char* a = 0x2000;

то это был бы адрес внешней памяти.

 

Попробуйте посмотреть здесь:

http://www.avrfreaks.net/index.php?name=PN...ewtopic&t=29499

 

Там, правда, речь идет о ATmega128, но принципы одинаковые.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А с чего вы решили, что данные переменные будут размещены во внешней памяти?

А это здесь причем? Во внешней или во внутренней, все равно глючит.

А во внешней вот почему:

EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x8090ff

 

Кстати, во втором случае, я не вижу инициализации указателя.

Подразумевается, что char* a используется для хранения различных строк.

 

Попробуйте посмотреть здесь:

http://www.avrfreaks.net/index.php?name=PN...ewtopic&t=29499

Там, правда, речь идет о ATmega128, но принципы одинаковые.

Да, они практически не отличаются. Читаю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А что, если вам попробовать запустить для начала тест внешней памяти/

Например, так:

 

#define EXT_MEM_START 0x1100

 

BOOL ram_test(void)

{

unsigned short j;

 

for (j = 0; j < RAM_SIZE; j++) _SFR_MEM8((j) + EXT_MEM_START) = (unsigned char)(j);

 

for (j = 0; j < RAM_SIZE; j++)

{

if (_SFR_MEM8((j) + EXT_MEM_START) != (unsigned char)(j)) return FALSE;

}

return TRUE;

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сделал тест памяти. Все работает.

С указателями ситуация так и не ясна. Когда он во встроенной памяти - все работает. Как только во внешнюю его помещаю, начинается ерунда.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сделал тест памяти. Все работает.

С указателями ситуация так и не ясна. Когда он во встроенной памяти - все работает. Как только во внешнюю его помещаю, начинается ерунда.

 

Это хорошо, что тест памяти работает - значит дело не в оборудовании, уже легче.

 

А попробуйте объявить указатель след. образом:

 

void ce210_print(volatile char *s)

{

while (*s) ce210_send(*s++);

}

 

или:

 

void ce210_print(char *s)

{

volatile char* a = s;

while (*a) ce210_send(*a++);

}

 

Думаю, что все заработает сразу :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

можно и без volatile:

 

void ce210_print(char *s)

{

register char ch;

 

while (1)

{

ch = *s;

if (ch == 0) break; //(или return)

ce210_send(ch);

s++;

}

}

 

при while (*a) ce210_send(*a++); да еще и volatile будет скорее всего 2 обращения к памяти, что в данном случае бессмысленно

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...