Самодельная Мега2560, 128А с памятью 512кб

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Платы пришли ещё 13 апреля, но только сегодня сумел забрать на почте:

Качество очень даже впечатлило. На коробке сверху плата под ATmega128a, снизу в том же форм-факторе под ATmega2560 и справа - под SRAM в 512килобайт. Для платы памяти есть все на 5шт, для остальных нет камней. В подарок в коробке оказалась картонная ручка "for PCB" уж не знаю зачем.

Осталось заказать камни. Продаваны по ссылкам выше - ни один не ответил ни на один заданный вопрос. Только автоответчик "не беспокойтесь, нам для ответа требуется время" .. напрягает. Вроде бы есть желающий продаван поставить по 10шт с оптовой алибабы.. видимо буду заказывать у него.

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Нашол у себя в загашнике 4 штуки w24512ak-15. Это CMOS Static RAM по 64 КБайта каждая.  Никому не надо?  Аддам за пузырь.  Новосибирск  

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Сделай лучше на них Мегу с расширенной ОЗУ. Должно вполне просто получиться. Только регистр нужен шустрый типа 74HC573D у меня другие не завелись.

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Не, мне они без надобности, сиравно скоро на кладбище переежять. Для моих поделок и 8кБ много. 

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Ладно, без пузыря аддам. :-)

Green
Offline
Зарегистрирован: 01.10.2015

Хе, хе, жаль что мне УЖЕ не надо. Пузыря не жалко.)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Вот в том-то и дело что УЖЕ не надо .. уже пришли 5шт на 512 килобайт и 10шт уже едут .. смысл в плате на 64кб? :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Ну наконец-то. Вчера забрал с почты 10шт ATmega2560-16au. По распаковке слегка прифигел: судя по маркировке, камни произведены на 13-й неделе (с26 марта по 1 апреля) 2018 года. О как! Запаял основную часть платы, проверил БП: на выходе 4.95в без нагрузки и 4.93в с токоотдачей 5А .. очень нефиговые эти RT8289 оказались. (картинко - кликабельно)

Светодиоды формата SMD так и не закупил, запаял мелкие круглые по 3мм. Конденсаторов по 22пф тоже пока не нашлось в загашниках. Так обойдется.. Уже завтра запаяю SPI м попытаюсь прошить загрузчик. БП выглядит конечно брутальненько так. Диоды шоттки на 3А. Тем не менее под нагрузкой 5А вроде даже и не греются. :)

P.S. Пока паял, пришла идея положить периферийные разьемы "на бок", кроме разъема с памятью .. блин, где эта мысля была раньше? :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Ура, ну не могу удержаться.. Вчерась (пока паял плату) дитенка самостоятельно (ну почти) впервые скомпилял себе на ноут под Убунтой драйвер Wi-Fi, который у него не встал при установке системы .. скоро, скоро будем принимать в свои ряды ещё одного "погромиста - сиониста". :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

И так, очередная крупная переработка (третья) arhat.h в связи с работой с расширенной памятью SRAM.

Имеем такую организацию адресов памяти:

1. 0x0000 .. 0x2200 (кажется так, не важно) - внутренняя SRAM меги 2560 (8200байт)

2. 0x2200 .. 0x7FFF -- общая страница внешнего SRAM (32кб), видна всегда.

3. 0x8000 .. 0xBFFF -- 15 сегментов SRAM по 16кб, переключаемые 1/2 (младшая тетрада) отдельного регистра блока расширенной памяти;

4. 0xC000 .. 0xFFFF -- 15 сегментов SRAM по 16кб, переключаемые второй половиной (старшая тетрада) того же внешнего регистра.

Запись во внешний регистр делается "ногодрыгом" по пинам WR & RD, с выставлением в порт А данных при отключенном интерфейсе xmem Меги.

п.1,п.2 - тривиальны, ибо обращение к этим участкам легко контролируется самим камнем автоматически и ничего специального разъяснять компилятору не требуется, просто надо указать "что теперь памяти больше", только и всего:

Вариант 1 (минималистический) описания платы: указываем в описании, что у этой платы оперативной памяти 64 килобайта, то есть разрешаем распределение всего адресного пространства и далее "ручками" контролируем, где что лежит .. но это не комильфо.

Вариант2 (это вот хочется запилить):

Было бы полезно объяснить компилятору и линковщику, что теперь у него есть доп. сегменты ОЗУ в виде .lpage0 .. .lpage14 и .upage0 .. .upage14, переменные которых надо размещать с соответствующих адресов п.3, 4. И далее в коде использовать атрибуты явного назначения сегмента ОЗУ переменным, размещаемым в заданном сегменте. Переключение сегментов в рантайм, скорее всего также придется контроллировать ручками .. но может есть какие-то идеи как это (процедуру смены контекста) всучить компилятору для автоконтроля?

В общем, вопросы на дкоторыми сейчас мучаюсь:

1. Можно ли завести свои сегменты памяти, аналогично .data, .bss и КАК это сделать?

2. Можно ли им назначить конкретные начальные адреса ОЗУ, в т.ч. и одинаковые? Например: .lpage0 = .lpage1. = .. = .lpage14 = 0x8000

3. Можно ли указать каким-то квалификатором что эту переменную (или блок таковых) надо размещать строго в этом сегменте ОЗУ?

4. Можно ли всучить компилятору процедуру переключения сегментов для автоконтроля при обращении к переменной?

Например что-то типа такого:

// компилятору всучена такая функция:
void xmem_lowPage(uint8_t lowNum);

// в коде имеем типа такой массив,
// размещаемый первым во втором сегменте расширенного ОЗУ:
uint8_t  attribute(__segment__(.lpage2))   buffer[4096];

// ...
// если в коде присутствует что-то типа такого:
for(int i=0; i<4096; i++){
  buffer[i] = 0;
}

// , то компилятор мог оценить какой сегмент сейчас активен и
// дополнить его так самостоятельно:

xmem_lowPage(2);
for(int i=0; i<4096; i++){
  buffer[i] = 0;
}

// правильно назначив начало массива скажем на начало этого сегмента (0x8000)

 

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015
Arhat109-2
Offline
Зарегистрирован: 24.09.2015

В этом случае, можно будет завести препроцессорные макросы типов, скрывающие атрибутирование сегмента ОЗУ, хотя бы типа так:

#define setVar(type, seg, name) \

type __atribute__(__segment__(seg)) name

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Да, это про то самое, спасибо.

То есть можно указать "хде" сложить переменную через такое:

uint8_t buffer[4096] __attribute__ ((section (".lpage2")));

И в настройке платы указать какие секции с каких адресов начинаются. Это сильно упрощает вопрос.

Остается понять КАК дополнить типовые секции для avr новыми названиями .. своими. И можно ли всучить компилятору контроль за переключением секций ОЗУ.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015
void initExtSRAM(void) __attribute__((naked, section(".init3")));
void initExtSRAM(void) {
  MCUCR |= (1 << SRE); // | (1 << SRW10); //wait 1 cycle
  XMCRA = 0; //|= (1 << SRW11);  //wait 1 state
  XMCRB |= (1 << XMM0); //PC7 released pin
  DDRC |= (1 << 7);
  PORTC &= ~(1 << 7);
}

Это я себе так делаю для 32к,

и компилятору говорю

128.menu.sram.32K.compiler.c.elf.extra_flags=-Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x8090ff

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Э-э-э, а почему конец памяти на 0x90FF? У вас разве внутренняя SRAM не экранирует начало внешней?

Эта часть - понятна, делал аналогично, просто расширяя доступность адресов до 0xFFFF. Но вот теперь хочется допилить до нормальной работы со всеми 512к через компилятор.

В общем, нашел что можно накатать свой сценарий линковщику что и как расмещать в памяти и какой .. осталось найти доку на линковщик. :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Ха дошло. Вы заэкранированный кусок в функции init() перегоняете на старшую часть адресов, управляя выводом PC7. Разумно. :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Пока нашел это: http://www.opennet.ru/docs/RUS/gnu_ld/gnuld-3.html#ss3.1 может кому пригодится тоже. Не AVR, но все же..

P.S. В общем, похоже можно тупо воспользоваться наличием в типовом сценарии линкера описаний типа *(.data*) и *(.bss*) то есть вставить в секции .data и .bss после данных ещё и всякие разные секции .data* - то есть похоже достаточно описать так:

uint8_t buffer[4096] __attribute__ ((section (".bss_lpage2")));

Использовать подсекции в .bss И указать опцией линковщика что секция .bss_lpage2 начинается с 0x8000 .. в общем что-то стало понятней, надо пгобовать.. :)

В общем все не так просто, ибо символ . может только возрастать в пределах секции. К счастью есть команда OVERLAY совмещающая несколько секций с одного адреса .. только вот есть ли она у линковщика avr-gcc?

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

В общем, пока понимаю так:

Получается что надо писать свой скрипт линкеру, где можно указать эту раскладку адресов выше на требуемые куски памяти, типа так:

MEMORY
{
  INTERNAL_RAM [rwa!x] : ORIGIN = 0x800200, LENGTH = 8000;
  COMMON_RAM [rwa!x] : ORIGIN = 0x802200, LENGTH = 32768-8200;
  LOW_WINDOW [rw!x] : ORIGIN = 0x808000, LENGTH = 16K;
  UPPER_WINDOW [rw!x] : ORIGIN = 0x80C000, LENGTH = 16K;
}

И далее добавлять алиасы на каждую физ.страничку, типа такого:

REGION_ALIAS(lowPage0, LOW_WINDOW);

REGION_ALIAS(lowPage1, LOW_WINDOW);

..
REGION_ALIAS(upperPage14, UPPER_WINDOW);

и уже потом определять секции типа так:

SECTIONS {
.lpage0 (NOLOAD) : { *(.lpage0) } > lowPage0

.lpage1 (NOLOAD) : { *(.lpage1) } > lowPage1
...
.upage14 (NOLOAD) : { *(.upage14) } > upperPage14
}

После этого уже можно будет привязывать данные к требуемым сегментам в программах через __atribute__((section(...))):

uint8_t buffer[4096] __attribute__ ((section (".lpage2")));

 

Н-да. Тут советов ждать не приходится, раз уж даже на киберфоруме, среди 42тыщ "программистов" не нашлось спецов по линкеру..

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Кто-то может подсказать какой из скриптов линкера надо брать за основу для правки? Для avr6 (mega2560) в Ардуино ИДЕ имеется 6 разных вариантов, отличающихся расширением .. ни один из них не подключается в явном виде при сборке ..

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Вау .. все получилось как надо!

#include <Arduino.h>

int lowbuffer[10] = {1,2,3,4,5,6,7,8,9,0}; // data
int buffer2[4000] __attribute__((section(".lpage2")));
int buffer4[4000] __attribute__((section(".hpage4")));

volatile int tmp; // bss

void setup() {}

void loop()
{
  for(int j=0; j<4000; j++){
      tmp = 55; // volatile!
      buffer2[j] = tmp;
      buffer4[j] = tmp*2;
  }
}

Результат реассемблирования через objdump (весь файл!):


/tmp/build8f6f47e5e1cc707751d4ea83951bb27b.tmp/sketch_jun05a.ino.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         00000000  00800200  000002c8  0000039c  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  1 .text         000002c8  00000000  00000000  000000d4  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .bss          0000000b  00800200  00800200  0000039c  2**0
                  ALLOC
  3 .lpage2       00001f40  00808000  00808000  0000039c  2**0
                  ALLOC
  4 .hpage4       00001f40  0080c000  0080c000  0000039c  2**0
                  ALLOC
  5 .comment      00000011  00000000  00000000  0000039c  2**0
                  CONTENTS, READONLY
  6 .note.gnu.avr.deviceinfo 00000040  00000000  00000000  000003b0  2**2
                  CONTENTS, READONLY
  7 .debug_info   00000bbc  00000000  00000000  000003f0  2**0
                  CONTENTS, READONLY, DEBUGGING
  8 .debug_abbrev 00000b1a  00000000  00000000  00000fac  2**0
                  CONTENTS, READONLY, DEBUGGING
  9 .debug_line   0000001a  00000000  00000000  00001ac6  2**0
                  CONTENTS, READONLY, DEBUGGING
 10 .debug_str    000003e6  00000000  00000000  00001ae0  2**0
                  CONTENTS, READONLY, DEBUGGING

Disassembly of section .text:

00000000 <__vectors>:
   0:	71 c0       	rjmp	.+226    	; 0xe4 <__ctors_end>
   2:	00 00       	nop
   4:	81 c0       	rjmp	.+258    	; 0x108 <__bad_interrupt>
   6:	00 00       	nop
   8:	7f c0       	rjmp	.+254    	; 0x108 <__bad_interrupt>
   a:	00 00       	nop
   c:	7d c0       	rjmp	.+250    	; 0x108 <__bad_interrupt>
   e:	00 00       	nop
  10:	7b c0       	rjmp	.+246    	; 0x108 <__bad_interrupt>
  12:	00 00       	nop
  14:	79 c0       	rjmp	.+242    	; 0x108 <__bad_interrupt>
  16:	00 00       	nop
  18:	77 c0       	rjmp	.+238    	; 0x108 <__bad_interrupt>
  1a:	00 00       	nop
  1c:	75 c0       	rjmp	.+234    	; 0x108 <__bad_interrupt>
  1e:	00 00       	nop
  20:	73 c0       	rjmp	.+230    	; 0x108 <__bad_interrupt>
  22:	00 00       	nop
  24:	71 c0       	rjmp	.+226    	; 0x108 <__bad_interrupt>
  26:	00 00       	nop
  28:	6f c0       	rjmp	.+222    	; 0x108 <__bad_interrupt>
  2a:	00 00       	nop
  2c:	6d c0       	rjmp	.+218    	; 0x108 <__bad_interrupt>
  2e:	00 00       	nop
  30:	6b c0       	rjmp	.+214    	; 0x108 <__bad_interrupt>
  32:	00 00       	nop
  34:	69 c0       	rjmp	.+210    	; 0x108 <__bad_interrupt>
  36:	00 00       	nop
  38:	67 c0       	rjmp	.+206    	; 0x108 <__bad_interrupt>
  3a:	00 00       	nop
  3c:	65 c0       	rjmp	.+202    	; 0x108 <__bad_interrupt>
  3e:	00 00       	nop
  40:	63 c0       	rjmp	.+198    	; 0x108 <__bad_interrupt>
  42:	00 00       	nop
  44:	61 c0       	rjmp	.+194    	; 0x108 <__bad_interrupt>
  46:	00 00       	nop
  48:	5f c0       	rjmp	.+190    	; 0x108 <__bad_interrupt>
  4a:	00 00       	nop
  4c:	5d c0       	rjmp	.+186    	; 0x108 <__bad_interrupt>
  4e:	00 00       	nop
  50:	5b c0       	rjmp	.+182    	; 0x108 <__bad_interrupt>
  52:	00 00       	nop
  54:	59 c0       	rjmp	.+178    	; 0x108 <__bad_interrupt>
  56:	00 00       	nop
  58:	57 c0       	rjmp	.+174    	; 0x108 <__bad_interrupt>
  5a:	00 00       	nop
  5c:	56 c0       	rjmp	.+172    	; 0x10a <__vector_23>
  5e:	00 00       	nop
  60:	53 c0       	rjmp	.+166    	; 0x108 <__bad_interrupt>
  62:	00 00       	nop
  64:	51 c0       	rjmp	.+162    	; 0x108 <__bad_interrupt>
  66:	00 00       	nop
  68:	4f c0       	rjmp	.+158    	; 0x108 <__bad_interrupt>
  6a:	00 00       	nop
  6c:	4d c0       	rjmp	.+154    	; 0x108 <__bad_interrupt>
  6e:	00 00       	nop
  70:	4b c0       	rjmp	.+150    	; 0x108 <__bad_interrupt>
  72:	00 00       	nop
  74:	49 c0       	rjmp	.+146    	; 0x108 <__bad_interrupt>
  76:	00 00       	nop
  78:	47 c0       	rjmp	.+142    	; 0x108 <__bad_interrupt>
  7a:	00 00       	nop
  7c:	45 c0       	rjmp	.+138    	; 0x108 <__bad_interrupt>
  7e:	00 00       	nop
  80:	43 c0       	rjmp	.+134    	; 0x108 <__bad_interrupt>
  82:	00 00       	nop
  84:	41 c0       	rjmp	.+130    	; 0x108 <__bad_interrupt>
  86:	00 00       	nop
  88:	3f c0       	rjmp	.+126    	; 0x108 <__bad_interrupt>
  8a:	00 00       	nop
  8c:	3d c0       	rjmp	.+122    	; 0x108 <__bad_interrupt>
  8e:	00 00       	nop
  90:	3b c0       	rjmp	.+118    	; 0x108 <__bad_interrupt>
  92:	00 00       	nop
  94:	39 c0       	rjmp	.+114    	; 0x108 <__bad_interrupt>
  96:	00 00       	nop
  98:	37 c0       	rjmp	.+110    	; 0x108 <__bad_interrupt>
  9a:	00 00       	nop
  9c:	35 c0       	rjmp	.+106    	; 0x108 <__bad_interrupt>
  9e:	00 00       	nop
  a0:	33 c0       	rjmp	.+102    	; 0x108 <__bad_interrupt>
  a2:	00 00       	nop
  a4:	31 c0       	rjmp	.+98     	; 0x108 <__bad_interrupt>
  a6:	00 00       	nop
  a8:	2f c0       	rjmp	.+94     	; 0x108 <__bad_interrupt>
  aa:	00 00       	nop
  ac:	2d c0       	rjmp	.+90     	; 0x108 <__bad_interrupt>
  ae:	00 00       	nop
  b0:	2b c0       	rjmp	.+86     	; 0x108 <__bad_interrupt>
  b2:	00 00       	nop
  b4:	29 c0       	rjmp	.+82     	; 0x108 <__bad_interrupt>
  b6:	00 00       	nop
  b8:	27 c0       	rjmp	.+78     	; 0x108 <__bad_interrupt>
  ba:	00 00       	nop
  bc:	25 c0       	rjmp	.+74     	; 0x108 <__bad_interrupt>
  be:	00 00       	nop
  c0:	23 c0       	rjmp	.+70     	; 0x108 <__bad_interrupt>
  c2:	00 00       	nop
  c4:	21 c0       	rjmp	.+66     	; 0x108 <__bad_interrupt>
  c6:	00 00       	nop
  c8:	1f c0       	rjmp	.+62     	; 0x108 <__bad_interrupt>
  ca:	00 00       	nop
  cc:	1d c0       	rjmp	.+58     	; 0x108 <__bad_interrupt>
  ce:	00 00       	nop
  d0:	1b c0       	rjmp	.+54     	; 0x108 <__bad_interrupt>
  d2:	00 00       	nop
  d4:	19 c0       	rjmp	.+50     	; 0x108 <__bad_interrupt>
  d6:	00 00       	nop
  d8:	17 c0       	rjmp	.+46     	; 0x108 <__bad_interrupt>
  da:	00 00       	nop
  dc:	15 c0       	rjmp	.+42     	; 0x108 <__bad_interrupt>
  de:	00 00       	nop
  e0:	13 c0       	rjmp	.+38     	; 0x108 <__bad_interrupt>
	...

000000e4 <__ctors_end>:
  e4:	11 24       	eor	r1, r1
  e6:	1f be       	out	0x3f, r1	; 63
  e8:	cf ef       	ldi	r28, 0xFF	; 255
  ea:	d1 e2       	ldi	r29, 0x21	; 33
  ec:	de bf       	out	0x3e, r29	; 62
  ee:	cd bf       	out	0x3d, r28	; 61
  f0:	00 e0       	ldi	r16, 0x00	; 0
  f2:	0c bf       	out	0x3c, r16	; 60

000000f4 <__do_clear_bss>:
  f4:	22 e0       	ldi	r18, 0x02	; 2
  f6:	a0 e0       	ldi	r26, 0x00	; 0
  f8:	b2 e0       	ldi	r27, 0x02	; 2
  fa:	01 c0       	rjmp	.+2      	; 0xfe <.do_clear_bss_start>

000000fc <.do_clear_bss_loop>:
  fc:	1d 92       	st	X+, r1

000000fe <.do_clear_bss_start>:
  fe:	ab 30       	cpi	r26, 0x0B	; 11
 100:	b2 07       	cpc	r27, r18
 102:	e1 f7       	brne	.-8      	; 0xfc <.do_clear_bss_loop>
 104:	4c d0       	rcall	.+152    	; 0x19e <main>
 106:	de c0       	rjmp	.+444    	; 0x2c4 <_exit>

00000108 <__bad_interrupt>:
 108:	7b cf       	rjmp	.-266    	; 0x0 <__vectors>

0000010a <__vector_23>:
 10a:	1f 92       	push	r1
 10c:	0f 92       	push	r0
 10e:	0f b6       	in	r0, 0x3f	; 63
 110:	0f 92       	push	r0
 112:	11 24       	eor	r1, r1
 114:	2f 93       	push	r18
 116:	3f 93       	push	r19
 118:	8f 93       	push	r24
 11a:	9f 93       	push	r25
 11c:	af 93       	push	r26
 11e:	bf 93       	push	r27
 120:	80 91 07 02 	lds	r24, 0x0207	; 0x800207 <timer0_millis>
 124:	90 91 08 02 	lds	r25, 0x0208	; 0x800208 <timer0_millis+0x1>
 128:	a0 91 09 02 	lds	r26, 0x0209	; 0x800209 <timer0_millis+0x2>
 12c:	b0 91 0a 02 	lds	r27, 0x020A	; 0x80020a <timer0_millis+0x3>
 130:	30 91 06 02 	lds	r19, 0x0206	; 0x800206 <timer0_fract>
 134:	23 e0       	ldi	r18, 0x03	; 3
 136:	23 0f       	add	r18, r19
 138:	2d 37       	cpi	r18, 0x7D	; 125
 13a:	20 f4       	brcc	.+8      	; 0x144 <__vector_23+0x3a>
 13c:	01 96       	adiw	r24, 0x01	; 1
 13e:	a1 1d       	adc	r26, r1
 140:	b1 1d       	adc	r27, r1
 142:	05 c0       	rjmp	.+10     	; 0x14e <__vector_23+0x44>
 144:	26 e8       	ldi	r18, 0x86	; 134
 146:	23 0f       	add	r18, r19
 148:	02 96       	adiw	r24, 0x02	; 2
 14a:	a1 1d       	adc	r26, r1
 14c:	b1 1d       	adc	r27, r1
 14e:	20 93 06 02 	sts	0x0206, r18	; 0x800206 <timer0_fract>
 152:	80 93 07 02 	sts	0x0207, r24	; 0x800207 <timer0_millis>
 156:	90 93 08 02 	sts	0x0208, r25	; 0x800208 <timer0_millis+0x1>
 15a:	a0 93 09 02 	sts	0x0209, r26	; 0x800209 <timer0_millis+0x2>
 15e:	b0 93 0a 02 	sts	0x020A, r27	; 0x80020a <timer0_millis+0x3>
 162:	80 91 02 02 	lds	r24, 0x0202	; 0x800202 <timer0_overflow_count>
 166:	90 91 03 02 	lds	r25, 0x0203	; 0x800203 <timer0_overflow_count+0x1>
 16a:	a0 91 04 02 	lds	r26, 0x0204	; 0x800204 <timer0_overflow_count+0x2>
 16e:	b0 91 05 02 	lds	r27, 0x0205	; 0x800205 <timer0_overflow_count+0x3>
 172:	01 96       	adiw	r24, 0x01	; 1
 174:	a1 1d       	adc	r26, r1
 176:	b1 1d       	adc	r27, r1
 178:	80 93 02 02 	sts	0x0202, r24	; 0x800202 <timer0_overflow_count>
 17c:	90 93 03 02 	sts	0x0203, r25	; 0x800203 <timer0_overflow_count+0x1>
 180:	a0 93 04 02 	sts	0x0204, r26	; 0x800204 <timer0_overflow_count+0x2>
 184:	b0 93 05 02 	sts	0x0205, r27	; 0x800205 <timer0_overflow_count+0x3>
 188:	bf 91       	pop	r27
 18a:	af 91       	pop	r26
 18c:	9f 91       	pop	r25
 18e:	8f 91       	pop	r24
 190:	3f 91       	pop	r19
 192:	2f 91       	pop	r18
 194:	0f 90       	pop	r0
 196:	0f be       	out	0x3f, r0	; 63
 198:	0f 90       	pop	r0
 19a:	1f 90       	pop	r1
 19c:	18 95       	reti

0000019e <main>:
 19e:	78 94       	sei
 1a0:	84 b5       	in	r24, 0x24	; 36
 1a2:	82 60       	ori	r24, 0x02	; 2
 1a4:	84 bd       	out	0x24, r24	; 36
 1a6:	84 b5       	in	r24, 0x24	; 36
 1a8:	81 60       	ori	r24, 0x01	; 1
 1aa:	84 bd       	out	0x24, r24	; 36
 1ac:	85 b5       	in	r24, 0x25	; 37
 1ae:	82 60       	ori	r24, 0x02	; 2
 1b0:	85 bd       	out	0x25, r24	; 37
 1b2:	85 b5       	in	r24, 0x25	; 37
 1b4:	81 60       	ori	r24, 0x01	; 1
 1b6:	85 bd       	out	0x25, r24	; 37
 1b8:	80 91 6e 00 	lds	r24, 0x006E	; 0x80006e <__heap_start+0x7fde6e>
 1bc:	81 60       	ori	r24, 0x01	; 1
 1be:	80 93 6e 00 	sts	0x006E, r24	; 0x80006e <__heap_start+0x7fde6e>
 1c2:	10 92 81 00 	sts	0x0081, r1	; 0x800081 <__heap_start+0x7fde81>
 1c6:	80 91 81 00 	lds	r24, 0x0081	; 0x800081 <__heap_start+0x7fde81>
 1ca:	82 60       	ori	r24, 0x02	; 2
 1cc:	80 93 81 00 	sts	0x0081, r24	; 0x800081 <__heap_start+0x7fde81>
 1d0:	80 91 81 00 	lds	r24, 0x0081	; 0x800081 <__heap_start+0x7fde81>
 1d4:	81 60       	ori	r24, 0x01	; 1
 1d6:	80 93 81 00 	sts	0x0081, r24	; 0x800081 <__heap_start+0x7fde81>
 1da:	80 91 80 00 	lds	r24, 0x0080	; 0x800080 <__heap_start+0x7fde80>
 1de:	81 60       	ori	r24, 0x01	; 1
 1e0:	80 93 80 00 	sts	0x0080, r24	; 0x800080 <__heap_start+0x7fde80>
 1e4:	80 91 b1 00 	lds	r24, 0x00B1	; 0x8000b1 <__heap_start+0x7fdeb1>
 1e8:	84 60       	ori	r24, 0x04	; 4
 1ea:	80 93 b1 00 	sts	0x00B1, r24	; 0x8000b1 <__heap_start+0x7fdeb1>
 1ee:	80 91 b0 00 	lds	r24, 0x00B0	; 0x8000b0 <__heap_start+0x7fdeb0>
 1f2:	81 60       	ori	r24, 0x01	; 1
 1f4:	80 93 b0 00 	sts	0x00B0, r24	; 0x8000b0 <__heap_start+0x7fdeb0>
 1f8:	80 91 91 00 	lds	r24, 0x0091	; 0x800091 <__heap_start+0x7fde91>
 1fc:	82 60       	ori	r24, 0x02	; 2
 1fe:	80 93 91 00 	sts	0x0091, r24	; 0x800091 <__heap_start+0x7fde91>
 202:	80 91 91 00 	lds	r24, 0x0091	; 0x800091 <__heap_start+0x7fde91>
 206:	81 60       	ori	r24, 0x01	; 1
 208:	80 93 91 00 	sts	0x0091, r24	; 0x800091 <__heap_start+0x7fde91>
 20c:	80 91 90 00 	lds	r24, 0x0090	; 0x800090 <__heap_start+0x7fde90>
 210:	81 60       	ori	r24, 0x01	; 1
 212:	80 93 90 00 	sts	0x0090, r24	; 0x800090 <__heap_start+0x7fde90>
 216:	80 91 a1 00 	lds	r24, 0x00A1	; 0x8000a1 <__heap_start+0x7fdea1>
 21a:	82 60       	ori	r24, 0x02	; 2
 21c:	80 93 a1 00 	sts	0x00A1, r24	; 0x8000a1 <__heap_start+0x7fdea1>
 220:	80 91 a1 00 	lds	r24, 0x00A1	; 0x8000a1 <__heap_start+0x7fdea1>
 224:	81 60       	ori	r24, 0x01	; 1
 226:	80 93 a1 00 	sts	0x00A1, r24	; 0x8000a1 <__heap_start+0x7fdea1>
 22a:	80 91 a0 00 	lds	r24, 0x00A0	; 0x8000a0 <__heap_start+0x7fdea0>
 22e:	81 60       	ori	r24, 0x01	; 1
 230:	80 93 a0 00 	sts	0x00A0, r24	; 0x8000a0 <__heap_start+0x7fdea0>
 234:	80 91 21 01 	lds	r24, 0x0121	; 0x800121 <__heap_start+0x7fdf21>
 238:	82 60       	ori	r24, 0x02	; 2
 23a:	80 93 21 01 	sts	0x0121, r24	; 0x800121 <__heap_start+0x7fdf21>
 23e:	80 91 21 01 	lds	r24, 0x0121	; 0x800121 <__heap_start+0x7fdf21>
 242:	81 60       	ori	r24, 0x01	; 1
 244:	80 93 21 01 	sts	0x0121, r24	; 0x800121 <__heap_start+0x7fdf21>
 248:	80 91 20 01 	lds	r24, 0x0120	; 0x800120 <__heap_start+0x7fdf20>
 24c:	81 60       	ori	r24, 0x01	; 1
 24e:	80 93 20 01 	sts	0x0120, r24	; 0x800120 <__heap_start+0x7fdf20>
 252:	80 91 7a 00 	lds	r24, 0x007A	; 0x80007a <__heap_start+0x7fde7a>
 256:	84 60       	ori	r24, 0x04	; 4
 258:	80 93 7a 00 	sts	0x007A, r24	; 0x80007a <__heap_start+0x7fde7a>
 25c:	80 91 7a 00 	lds	r24, 0x007A	; 0x80007a <__heap_start+0x7fde7a>
 260:	82 60       	ori	r24, 0x02	; 2
 262:	80 93 7a 00 	sts	0x007A, r24	; 0x80007a <__heap_start+0x7fde7a>
 266:	80 91 7a 00 	lds	r24, 0x007A	; 0x80007a <__heap_start+0x7fde7a>
 26a:	81 60       	ori	r24, 0x01	; 1
 26c:	80 93 7a 00 	sts	0x007A, r24	; 0x80007a <__heap_start+0x7fde7a>
 270:	80 91 7a 00 	lds	r24, 0x007A	; 0x80007a <__heap_start+0x7fde7a>
 274:	80 68       	ori	r24, 0x80	; 128
 276:	80 93 7a 00 	sts	0x007A, r24	; 0x80007a <__heap_start+0x7fde7a>
 27a:	10 92 c1 00 	sts	0x00C1, r1	; 0x8000c1 <__heap_start+0x7fdec1>
 27e:	c0 e0       	ldi	r28, 0x00	; 0
 280:	d0 e0       	ldi	r29, 0x00	; 0
 282:	07 e3       	ldi	r16, 0x37	; 55
 284:	10 e0       	ldi	r17, 0x00	; 0
 286:	e0 e0       	ldi	r30, 0x00	; 0
 288:	f0 e8       	ldi	r31, 0x80	; 128
 28a:	a0 e0       	ldi	r26, 0x00	; 0
 28c:	b0 ec       	ldi	r27, 0xC0	; 192
 28e:	10 93 01 02 	sts	0x0201, r17	; 0x800201 <_edata+0x1>
 292:	00 93 00 02 	sts	0x0200, r16	; 0x800200 <_edata>
 296:	80 91 00 02 	lds	r24, 0x0200	; 0x800200 <_edata>
 29a:	90 91 01 02 	lds	r25, 0x0201	; 0x800201 <_edata+0x1>
 29e:	81 93       	st	Z+, r24
 2a0:	91 93       	st	Z+, r25
 2a2:	80 91 00 02 	lds	r24, 0x0200	; 0x800200 <_edata>
 2a6:	90 91 01 02 	lds	r25, 0x0201	; 0x800201 <_edata+0x1>
 2aa:	88 0f       	add	r24, r24
 2ac:	99 1f       	adc	r25, r25
 2ae:	8d 93       	st	X+, r24
 2b0:	9d 93       	st	X+, r25
 2b2:	8f e9       	ldi	r24, 0x9F	; 159
 2b4:	e0 34       	cpi	r30, 0x40	; 64
 2b6:	f8 07       	cpc	r31, r24
 2b8:	51 f7       	brne	.-44     	; 0x28e <main+0xf0>
 2ba:	20 97       	sbiw	r28, 0x00	; 0
 2bc:	21 f3       	breq	.-56     	; 0x286 <main+0xe8>
 2be:	0e 94 00 00 	call	0	; 0x0 <__vectors>
 2c2:	e1 cf       	rjmp	.-62     	; 0x286 <main+0xe8>

000002c4 <_exit>:
 2c4:	f8 94       	cli

000002c6 <__stop_program>:
 2c6:	ff cf       	rjmp	.-2      	; 0x2c6 <__stop_program>

 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Ещё раз спасибки автору http://arduino.ru/forum/obshchii/nastroika-kompilyatsii-v-arduino-ide - оказалось очень полезно.

Добавил согласно прописанному вывод avr-objdump в компиляцю, дополнительно прописал отдельную плату в board.txt типа так:

##############################################################

sram.name=Extended SRAM 512kbytes

sram.upload.tool=avrdude

sram.bootloader.tool=avrdude
sram.bootloader.low_fuses=0xFF
sram.bootloader.unlock_bits=0x3F
sram.bootloader.lock_bits=0x0F

sram.build.f_cpu=16000000L
sram.build.core=arduino
sram.menu.cpu.atmega2560.build.variant=sram

## ESRAM512k for ATmega2560
## -------------------------
sram.menu.cpu.atmega2560=ATmega2560

sram.menu.cpu.atmega2560.upload.protocol=wiring
sram.menu.cpu.atmega2560.upload.maximum_size=253952
sram.menu.cpu.atmega2560.upload.maximum_data_size=32256
sram.menu.cpu.atmega2560.upload.speed=115200

sram.menu.cpu.atmega2560.bootloader.high_fuses=0xD8
sram.menu.cpu.atmega2560.bootloader.extended_fuses=0xFD
sram.menu.cpu.atmega2560.bootloader.file=stk500v2/stk500boot_v2_mega2560.hex

sram.menu.cpu.atmega2560.build.mcu=atmega2560
sram.menu.cpu.atmega2560.build.board=AVR_MEGA2560

## Special linker script for paging memory and move heap up the stack:

sram.menu.cpu.atmega2560.compiler.c.elf.extra_flags=-T{build.variant.path}/avr6.x -Wl,--defsym=__heap_start=0x802200,--defsym=__heap_end=0x807fff
#sram.menu.cpu.atmega2560.compiler.c.extra_flags=

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

Дополнительно создан каталог с "платой" в variants/sram, что и указано в boards.txt и в него положен свой файл скрипта линкера avr6.x Пока только для линковки по умолчанию (остальные вроде для ИДЕ не нужны):

/* Default linker script, for normal executables */
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
OUTPUT_ARCH(avr:6)
MEMORY
{
  text       (rx)   : ORIGIN = 0, LENGTH = 1024K
  data       (rw!x) : ORIGIN = 0x800200, LENGTH = 32K-0x200
  wndLow     (rw!x) : ORIGIN = 0x808000, LENGTH = 16K
  wndHigh    (rw!x) : ORIGIN = 0x80C000, LENGTH = 16K
  eeprom     (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
  fuse       (rw!x) : ORIGIN = 0x820000, LENGTH = 1K
  lock       (rw!x) : ORIGIN = 0x830000, LENGTH = 1K
  signature  (rw!x) : ORIGIN = 0x840000, LENGTH = 1K
}
/* page aliases for window regions */
REGION_ALIAS("lowPage0", wndLow);
REGION_ALIAS("lowPage1", wndLow);
REGION_ALIAS("lowPage2", wndLow);
REGION_ALIAS("lowPage3", wndLow);
REGION_ALIAS("lowPage4", wndLow);
REGION_ALIAS("lowPage5", wndLow);
REGION_ALIAS("lowPage6", wndLow);
REGION_ALIAS("lowPage7", wndLow);
REGION_ALIAS("lowPage8", wndLow);
REGION_ALIAS("lowPage9", wndLow);
REGION_ALIAS("lowPage10", wndLow);
REGION_ALIAS("lowPage11", wndLow);
REGION_ALIAS("lowPage12", wndLow);
REGION_ALIAS("lowPage13", wndLow);
REGION_ALIAS("lowPage14", wndLow);
REGION_ALIAS("lowPage15", wndLow);

REGION_ALIAS("highPage0", wndHigh);
REGION_ALIAS("highPage1", wndHigh);
REGION_ALIAS("highPage2", wndHigh);
REGION_ALIAS("highPage3", wndHigh);
REGION_ALIAS("highPage4", wndHigh);
REGION_ALIAS("highPage5", wndHigh);
REGION_ALIAS("highPage6", wndHigh);
REGION_ALIAS("highPage7", wndHigh);
REGION_ALIAS("highPage8", wndHigh);
REGION_ALIAS("highPage9", wndHigh);
REGION_ALIAS("highPage10", wndHigh);
REGION_ALIAS("highPage11", wndHigh);
REGION_ALIAS("highPage12", wndHigh);
REGION_ALIAS("highPage13", wndHigh);
REGION_ALIAS("highPage14", wndHigh);
REGION_ALIAS("highPage15", wndHigh);

SECTIONS
{
  /* Read-only sections, merged into text segment: */
  .hash          : { *(.hash)		}
  .dynsym        : { *(.dynsym)		}
  .dynstr        : { *(.dynstr)		}
  .gnu.version   : { *(.gnu.version)	}
  .gnu.version_d : { *(.gnu.version_d)	}
  .gnu.version_r : { *(.gnu.version_r)	}
  .rel.init      : { *(.rel.init)	}
  .rela.init     : { *(.rela.init)	}
  .rel.text      :
    {
      *(.rel.text)
      *(.rel.text.*)
      *(.rel.gnu.linkonce.t*)
    }
  .rela.text     :
    {
      *(.rela.text)
      *(.rela.text.*)
      *(.rela.gnu.linkonce.t*)
    }
  .rel.fini      : { *(.rel.fini)	}
  .rela.fini     : { *(.rela.fini)	}
  .rel.rodata    :
    {
      *(.rel.rodata)
      *(.rel.rodata.*)
      *(.rel.gnu.linkonce.r*)
    }
  .rela.rodata   :
    {
      *(.rela.rodata)
      *(.rela.rodata.*)
      *(.rela.gnu.linkonce.r*)
    }
  .rel.data      :
    {
      *(.rel.data)
      *(.rel.data.*)
      *(.rel.gnu.linkonce.d*)
    }
  .rela.data     :
    {
      *(.rela.data)
      *(.rela.data.*)
      *(.rela.gnu.linkonce.d*)
    }
  .rel.ctors     : { *(.rel.ctors)	}
  .rela.ctors    : { *(.rela.ctors)	}
  .rel.dtors     : { *(.rel.dtors)	}
  .rela.dtors    : { *(.rela.dtors)	}
  .rel.got       : { *(.rel.got)	}
  .rela.got      : { *(.rela.got)	}
  .rel.bss       : { *(.rel.bss)	}
  .rela.bss      : { *(.rela.bss)	}
  .rel.plt       : { *(.rel.plt)	}
  .rela.plt      : { *(.rela.plt)	}

  /* Internal text space or external memory.  */
  .text   :
  {
    *(.vectors)
    KEEP(*(.vectors))
    /* For data that needs to reside in the lower 64k of progmem.  */
     *(.progmem.gcc*)
    /* PR 13812: Placing the trampolines here gives a better chance
       that they will be in range of the code that uses them.  */
    . = ALIGN(2);
     __trampolines_start = . ;
    /* The jump trampolines for the 16-bit limited relocs will reside here.  */
    *(.trampolines)
    *(.trampolines*)
     __trampolines_end = . ;
     *(.progmem*)
    . = ALIGN(2);
    /* For future tablejump instruction arrays for 3 byte pc devices.
       We don't relax jump/call instructions within these sections.  */
    *(.jumptables)
    *(.jumptables*)
    /* For code that needs to reside in the lower 128k progmem.  */
    *(.lowtext)
    *(.lowtext*)
     __ctors_start = . ;
     *(.ctors)
     __ctors_end = . ;
     __dtors_start = . ;
     *(.dtors)
     __dtors_end = . ;
    KEEP(SORT(*)(.ctors))
    KEEP(SORT(*)(.dtors))
    /* From this point on, we don't bother about wether the insns are below or above the 16 bits boundary.  */
    *(.init0)  /* Start here after reset.  */
    KEEP (*(.init0))
    *(.init1)
    KEEP (*(.init1))
    *(.init2)  /* Clear __zero_reg__, set up stack pointer.  */
    KEEP (*(.init2))
    *(.init3)
    KEEP (*(.init3))
    *(.init4)  /* Initialize data and BSS.  */
    KEEP (*(.init4))
    *(.init5)
    KEEP (*(.init5))
    *(.init6)  /* C++ constructors.  */
    KEEP (*(.init6))
    *(.init7)
    KEEP (*(.init7))
    *(.init8)
    KEEP (*(.init8))
    *(.init9)  /* Call main().  */
    KEEP (*(.init9))
    *(.text)
    . = ALIGN(2);
     *(.text.*)
    . = ALIGN(2);
    *(.fini9)  /* _exit() starts here.  */
    KEEP (*(.fini9))
    *(.fini8)
    KEEP (*(.fini8))
    *(.fini7)
    KEEP (*(.fini7))
    *(.fini6)  /* C++ destructors.  */
    KEEP (*(.fini6))
    *(.fini5)
    KEEP (*(.fini5))
    *(.fini4)
    KEEP (*(.fini4))
    *(.fini3)
    KEEP (*(.fini3))
    *(.fini2)
    KEEP (*(.fini2))
    *(.fini1)
    KEEP (*(.fini1))
    *(.fini0)  /* Infinite loop after program termination.  */
    KEEP (*(.fini0))
     _etext = . ;
  }  > text

  .data :
  {
     PROVIDE (__data_start = .) ;
    /* --gc-sections will delete empty .data. This leads to wrong start
       addresses for subsequent sections because -Tdata= from the command
       line will have no effect, see PR13697.  Thus, keep .data  */
    KEEP (*(.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   : AT (ADDR (.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 = . ;
     PROVIDE (__heap_start = .) ;
  }  > data

  /* low window page segments as BSS only! not initialized */
  .lpage0  (NOLOAD) : { *(.lpage0) } > lowPage0
  .lpage1  (NOLOAD) : { *(.lpage1) } > lowPage1
  .lpage2  (NOLOAD) : { *(.lpage2) } > lowPage2
  .lpage3  (NOLOAD) : { *(.lpage3) } > lowPage3
  .lpage4  (NOLOAD) : { *(.lpage4) } > lowPage4
  .lpage5  (NOLOAD) : { *(.lpage5) } > lowPage5
  .lpage6  (NOLOAD) : { *(.lpage6) } > lowPage6
  .lpage7  (NOLOAD) : { *(.lpage7) } > lowPage7
  .lpage8  (NOLOAD) : { *(.lpage8) } > lowPage8
  .lpage9  (NOLOAD) : { *(.lpage9) } > lowPage9
  .lpage10 (NOLOAD) : { *(.lpage10) } > lowPage10
  .lpage11 (NOLOAD) : { *(.lpage11) } > lowPage11
  .lpage12 (NOLOAD) : { *(.lpage12) } > lowPage12
  .lpage13 (NOLOAD) : { *(.lpage13) } > lowPage13
  .lpage14 (NOLOAD) : { *(.lpage14) } > lowPage14
  .lpage15 (NOLOAD) : { *(.lpage15) } > lowPage15

  .hpage0 (NOLOAD) : { *(.hpage0) } > highPage0
  .hpage1 (NOLOAD) : { *(.hpage1) } > highPage1
  .hpage2 (NOLOAD) : { *(.hpage2) } > highPage2
  .hpage3 (NOLOAD) : { *(.hpage3) } > highPage3
  .hpage4 (NOLOAD) : { *(.hpage4) } > highPage4
  .hpage5 (NOLOAD) : { *(.hpage5) } > highPage5
  .hpage6 (NOLOAD) : { *(.hpage6) } > highPage6
  .hpage7 (NOLOAD) : { *(.hpage7) } > highPage7
  .hpage8 (NOLOAD) : { *(.hpage8) } > highPage8
  .hpage9 (NOLOAD) : { *(.hpage9) } > highPage9
  .hpage10 (NOLOAD) : { *(.hpage10) } > highPage10
  .hpage11 (NOLOAD) : { *(.hpage11) } > highPage11
  .hpage12 (NOLOAD) : { *(.hpage12) } > highPage12
  .hpage13 (NOLOAD) : { *(.hpage13) } > highPage13
  .hpage14 (NOLOAD) : { *(.hpage14) } > highPage14
  .hpage15 (NOLOAD) : { *(.hpage15) } > highPage15

  .eeprom  :
  {
    /* See .data above...  */
    KEEP(*(.eeprom*))
     __eeprom_end = . ;
  }  > eeprom
  .fuse  :
  {
    KEEP(*(.fuse))
    KEEP(*(.lfuse))
    KEEP(*(.hfuse))
    KEEP(*(.efuse))
  }  > fuse
  .lock  :
  {
    KEEP(*(.lock*))
  }  > lock
  .signature  :
  {
    KEEP(*(.signature*))
  }  > signature
  /* Stabs debugging sections.  */
  .stab 0 : { *(.stab) }
  .stabstr 0 : { *(.stabstr) }
  .stab.excl 0 : { *(.stab.excl) }
  .stab.exclstr 0 : { *(.stab.exclstr) }
  .stab.index 0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment 0 : { *(.comment) }
  .note.gnu.build-id : { *(.note.gnu.build-id) }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the beginning
     of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end ) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  /* SGI/MIPS DWARF 2 extensions */
  .debug_weaknames 0 : { *(.debug_weaknames) }
  .debug_funcnames 0 : { *(.debug_funcnames) }
  .debug_typenames 0 : { *(.debug_typenames) }
  .debug_varnames  0 : { *(.debug_varnames) }
  /* DWARF 3 */
  .debug_pubtypes 0 : { *(.debug_pubtypes) }
  .debug_ranges   0 : { *(.debug_ranges) }
  /* DWARF Extension.  */
  .debug_macro    0 : { *(.debug_macro) }
}

собственно и усё .. теперь можно обьявлять данные в нужных секциях и листать их вручную.

Да, ещё в boards.txt указано что "куча" malloc() тут начинается с точки расширения SRAM, "за" стеком, который как обычно устанавливается на конец встроенной SRAM через скрипт старта ctors и константу RAMEND, определенную в недрах io.h и файлах камней.. размер памяти под переменные ограничен 32кб по размеру секции .data. ну .. чтобы "жизнь медом не казалась" :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Макросы для упрощения назначения страниц объектам данных:

#define PAGE_LOW(pageNum) __attribute__((section(".lpage" #pageNum)))
#define PAGE_HIGH(pageNum) __attribute__((section(".hpage" #pageNum)))

// и тогда в коде можно так:

int buffer[8000] PAGE_LOW(2);

 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Упс. Выкладываю исправленный avr6.x:

/* Default linker script, for normal executables */
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
OUTPUT_ARCH(avr:6)
MEMORY
{
  text       (rx)   : ORIGIN = 0, LENGTH = 1024K
  data       (rw!x) : ORIGIN = 0x800200, LENGTH = 32K-0x200
  wndLow     (rw!x) : ORIGIN = 0x808000, LENGTH = 16K
  wndHigh    (rw!x) : ORIGIN = 0x80C000, LENGTH = 16K
  eeprom     (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
  fuse       (rw!x) : ORIGIN = 0x820000, LENGTH = 1K
  lock       (rw!x) : ORIGIN = 0x830000, LENGTH = 1K
  signature  (rw!x) : ORIGIN = 0x840000, LENGTH = 1K
}

SECTIONS
{
  /* Read-only sections, merged into text segment: */
  .hash          : { *(.hash)		}
  .dynsym        : { *(.dynsym)		}
  .dynstr        : { *(.dynstr)		}
  .gnu.version   : { *(.gnu.version)	}
  .gnu.version_d : { *(.gnu.version_d)	}
  .gnu.version_r : { *(.gnu.version_r)	}
  .rel.init      : { *(.rel.init)	}
  .rela.init     : { *(.rela.init)	}
  .rel.text      :
    {
      *(.rel.text)
      *(.rel.text.*)
      *(.rel.gnu.linkonce.t*)
    }
  .rela.text     :
    {
      *(.rela.text)
      *(.rela.text.*)
      *(.rela.gnu.linkonce.t*)
    }
  .rel.fini      : { *(.rel.fini)	}
  .rela.fini     : { *(.rela.fini)	}
  .rel.rodata    :
    {
      *(.rel.rodata)
      *(.rel.rodata.*)
      *(.rel.gnu.linkonce.r*)
    }
  .rela.rodata   :
    {
      *(.rela.rodata)
      *(.rela.rodata.*)
      *(.rela.gnu.linkonce.r*)
    }
  .rel.data      :
    {
      *(.rel.data)
      *(.rel.data.*)
      *(.rel.gnu.linkonce.d*)
    }
  .rela.data     :
    {
      *(.rela.data)
      *(.rela.data.*)
      *(.rela.gnu.linkonce.d*)
    }
  .rel.ctors     : { *(.rel.ctors)	}
  .rela.ctors    : { *(.rela.ctors)	}
  .rel.dtors     : { *(.rel.dtors)	}
  .rela.dtors    : { *(.rela.dtors)	}
  .rel.got       : { *(.rel.got)	}
  .rela.got      : { *(.rela.got)	}
  .rel.bss       : { *(.rel.bss)	}
  .rela.bss      : { *(.rela.bss)	}
  .rel.plt       : { *(.rel.plt)	}
  .rela.plt      : { *(.rela.plt)	}

  /* Internal text space or external memory.  */
  .text   :
  {
    *(.vectors)
    KEEP(*(.vectors))
    /* For data that needs to reside in the lower 64k of progmem.  */
     *(.progmem.gcc*)
    /* PR 13812: Placing the trampolines here gives a better chance
       that they will be in range of the code that uses them.  */
    . = ALIGN(2);
     __trampolines_start = . ;
    /* The jump trampolines for the 16-bit limited relocs will reside here.  */
    *(.trampolines)
    *(.trampolines*)
     __trampolines_end = . ;
     *(.progmem*)
    . = ALIGN(2);
    /* For future tablejump instruction arrays for 3 byte pc devices.
       We don't relax jump/call instructions within these sections.  */
    *(.jumptables)
    *(.jumptables*)
    /* For code that needs to reside in the lower 128k progmem.  */
    *(.lowtext)
    *(.lowtext*)
     __ctors_start = . ;
     *(.ctors)
     __ctors_end = . ;
     __dtors_start = . ;
     *(.dtors)
     __dtors_end = . ;
    KEEP(SORT(*)(.ctors))
    KEEP(SORT(*)(.dtors))
    /* From this point on, we don't bother about wether the insns are below or above the 16 bits boundary.  */
    *(.init0)  /* Start here after reset.  */
    KEEP (*(.init0))
    *(.init1)
    KEEP (*(.init1))
    *(.init2)  /* Clear __zero_reg__, set up stack pointer.  */
    KEEP (*(.init2))
    *(.init3)
    KEEP (*(.init3))
    *(.init4)  /* Initialize data and BSS.  */
    KEEP (*(.init4))
    *(.init5)
    KEEP (*(.init5))
    *(.init6)  /* C++ constructors.  */
    KEEP (*(.init6))
    *(.init7)
    KEEP (*(.init7))
    *(.init8)
    KEEP (*(.init8))
    *(.init9)  /* Call main().  */
    KEEP (*(.init9))
    *(.text)
    . = ALIGN(2);
     *(.text.*)
    . = ALIGN(2);
    *(.fini9)  /* _exit() starts here.  */
    KEEP (*(.fini9))
    *(.fini8)
    KEEP (*(.fini8))
    *(.fini7)
    KEEP (*(.fini7))
    *(.fini6)  /* C++ destructors.  */
    KEEP (*(.fini6))
    *(.fini5)
    KEEP (*(.fini5))
    *(.fini4)
    KEEP (*(.fini4))
    *(.fini3)
    KEEP (*(.fini3))
    *(.fini2)
    KEEP (*(.fini2))
    *(.fini1)
    KEEP (*(.fini1))
    *(.fini0)  /* Infinite loop after program termination.  */
    KEEP (*(.fini0))
     _etext = . ;
  }  > text

  .data :
  {
     PROVIDE (__data_start = .) ;
    /* --gc-sections will delete empty .data. This leads to wrong start
       addresses for subsequent sections because -Tdata= from the command
       line will have no effect, see PR13697.  Thus, keep .data  */
    KEEP (*(.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   : AT (ADDR (.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 = . ;
     PROVIDE (__heap_start = .) ;
  }  > data

  /* Window page segments for extSRAM as BSS only! not initialized, not loaded to elf! */
  .lpage0  ORIGIN(wndLow) (NOLOAD) : { *(.lpage0)  } > wndLow
  .lpage1  ORIGIN(wndLow) (NOLOAD) : { *(.lpage1)  } > wndLow
  .lpage2  ORIGIN(wndLow) (NOLOAD) : { *(.lpage2)  } > wndLow
  .lpage3  ORIGIN(wndLow) (NOLOAD) : { *(.lpage3)  } > wndLow
  .lpage4  ORIGIN(wndLow) (NOLOAD) : { *(.lpage4)  } > wndLow
  .lpage5  ORIGIN(wndLow) (NOLOAD) : { *(.lpage5)  } > wndLow
  .lpage6  ORIGIN(wndLow) (NOLOAD) : { *(.lpage6)  } > wndLow
  .lpage7  ORIGIN(wndLow) (NOLOAD) : { *(.lpage7)  } > wndLow
  .lpage8  ORIGIN(wndLow) (NOLOAD) : { *(.lpage8)  } > wndLow
  .lpage9  ORIGIN(wndLow) (NOLOAD) : { *(.lpage9)  } > wndLow
  .lpage10 ORIGIN(wndLow) (NOLOAD) : { *(.lpage10) } > wndLow
  .lpage11 ORIGIN(wndLow) (NOLOAD) : { *(.lpage11) } > wndLow
  .lpage12 ORIGIN(wndLow) (NOLOAD) : { *(.lpage12) } > wndLow
  .lpage13 ORIGIN(wndLow) (NOLOAD) : { *(.lpage13) } > wndLow
  .lpage14 ORIGIN(wndLow) (NOLOAD) : { *(.lpage14) } > wndLow
  .lpage15 ORIGIN(wndLow) (NOLOAD) : { *(.lpage15) } > wndLow

  .hpage0  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage0)  } > wndHigh
  .hpage1  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage1)  } > wndHigh
  .hpage2  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage2)  } > wndHigh
  .hpage3  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage3)  } > wndHigh
  .hpage4  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage4)  } > wndHigh
  .hpage5  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage5)  } > wndHigh
  .hpage6  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage6)  } > wndHigh
  .hpage7  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage7)  } > wndHigh
  .hpage8  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage8)  } > wndHigh
  .hpage9  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage9)  } > wndHigh
  .hpage10 ORIGIN(wndHigh) (NOLOAD) : { *(.hpage10) } > wndHigh
  .hpage11 ORIGIN(wndHigh) (NOLOAD) : { *(.hpage11) } > wndHigh
  .hpage12 ORIGIN(wndHigh) (NOLOAD) : { *(.hpage12) } > wndHigh
  .hpage13 ORIGIN(wndHigh) (NOLOAD) : { *(.hpage13) } > wndHigh
  .hpage14 ORIGIN(wndHigh) (NOLOAD) : { *(.hpage14) } > wndHigh
  .hpage15 ORIGIN(wndHigh) (NOLOAD) : { *(.hpage15) } > wndHigh

  .eeprom  :
  {
    /* See .data above...  */
    KEEP(*(.eeprom*))
     __eeprom_end = . ;
  }  > eeprom
  .fuse  :
  {
    KEEP(*(.fuse))
    KEEP(*(.lfuse))
    KEEP(*(.hfuse))
    KEEP(*(.efuse))
  }  > fuse
  .lock  :
  {
    KEEP(*(.lock*))
  }  > lock
  .signature  :
  {
    KEEP(*(.signature*))
  }  > signature
  /* Stabs debugging sections.  */
  .stab 0 : { *(.stab) }
  .stabstr 0 : { *(.stabstr) }
  .stab.excl 0 : { *(.stab.excl) }
  .stab.exclstr 0 : { *(.stab.exclstr) }
  .stab.index 0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment 0 : { *(.comment) }
  .note.gnu.build-id : { *(.note.gnu.build-id) }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the beginning
     of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end ) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  /* SGI/MIPS DWARF 2 extensions */
  .debug_weaknames 0 : { *(.debug_weaknames) }
  .debug_funcnames 0 : { *(.debug_funcnames) }
  .debug_typenames 0 : { *(.debug_typenames) }
  .debug_varnames  0 : { *(.debug_varnames) }
  /* DWARF 3 */
  .debug_pubtypes 0 : { *(.debug_pubtypes) }
  .debug_ranges   0 : { *(.debug_ranges) }
  /* DWARF Extension.  */
  .debug_macro    0 : { *(.debug_macro) }
}

Предыдущий вариант оказалось что пришивает секции друг к другу, если они из одного окна. Этот ведет себя верно во всех случаях.

Остается только допереть КАК сделать возможность распихивания константно проинициализированных данных, аналогично секции .data

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Сделал вот такой кусок в boards.txt:

##-- описание новых пунктов меню - в самое начало файла boards.txt:
menu.BOARD=board subtype
menu.cpu=Processor
menu.clock=Clock cpu/board
menu.BOD=BOD
menu.LTO=Compiler LTO
menu.BOOT=BOOT options
##-- собственно сборка для всех "мег" совместимой серии:

##############################################################

megaAll.name=*** ATmega640/1280/1281/2560/2561 ***

###--- common settings for all boards and MCU ---###
megaAll.upload.tool=avrdude
megaAll.upload.speed=115200
megaAll.upload.protocol=wiring

megaAll.bootloader.tool=avrdude
megaAll.bootloader.unlock_bits=0x3F
megaAll.bootloader.lock_bits=0x0F

megaAll.build.core=arduino

##--- board selector submenu ---##
megaAll.menu.BOARD.arduino2560=Arduino Mega 2560 (common)
megaAll.menu.BOARD.arduino2560.upload.maximum_data_size=8192
megaAll.menu.BOARD.arduino2560.build.variant=mega
megaAll.menu.BOARD.arduino2560.build.board=AVR_MEGA2560

megaAll.menu.BOARD.megaADK=Arduino Mega ADK
megaAll.menu.BOARD.megaADK.upload.maximum_data_size=8192
megaAll.menu.BOARD.megaADK.variant=mega
megaAll.menu.BOARD.megaADK.build.board=AVR_ADK

megaAll.menu.BOARD.esram32=with ext.SRAM 32 kbytes
megaAll.menu.BOARD.esram32.upload.maximum_data_size=32256
megaAll.menu.BOARD.esram32.variant=mega
megaAll.menu.BOARD.esram32.compiler.c.elf.extra_flags={compiler.c.elf.extra_flags} -Wl,--defsym=__heap_start=0x802200,--defsym=__heap_end=0x807fff

megaAll.menu.BOARD.esram64=with ext.SRAM 64 kbytes
megaAll.menu.BOARD.esram64.upload.maximum_data_size=65024
megaAll.menu.BOARD.esram64.variant=mega
megaAll.menu.BOARD.esram64.compiler.c.elf.extra_flags={compiler.c.elf.extra_flags} -Wl,--defsym=__heap_start=0x802200,--defsym=__heap_end=0x80ffff

megaAll.menu.BOARD.esram5=MYPK-xxx with ext.SRAM 512kbytes
megaAll.menu.BOARD.esram5.upload.maximum_data_size=32256
megaAll.menu.BOARD.esram5.variant=sram
megaAll.menu.BOARD.esram5.build.board=AVR_MEGA2560
megaAll.menu.BOARD.esram5.compiler.c.elf.extra_flags={compiler.c.elf.extra_flags} -T{build.variant.path}/avr6.x -Wl,--defsym=__heap_start=0x802200,--defsym=__heap_end=0x807fff

##--- CPU submenu ---
megaAll.menu.cpu.atmega2560=ATmega2560
megaAll.menu.cpu.atmega2560.build.mcu=atmega2560
megaAll.menu.cpu.atmega2560.build.core=arduino
megaAll.menu.cpu.atmega2560.build.board=AVR_ATmega2560
megaAll.menu.cpu.atmega2560.BOOT.stk500v2.upload.maximum_size=258048
megaAll.menu.cpu.atmega2560.BOOT.optiboot.upload.maximum_size=261120

# special for 1280 arduino loader
megaAll.menu.cpu.atmega1280=ATmega1280
megaAll.menu.cpu.atmega1280.build.mcu=atmega1280
megaAll.menu.cpu.atmega1280.BOARD.mega2560.build.board=AVR_MEGA
megaAll.menu.cpu.atmega1280.BOOT.1280spec=mega1280 arduino bootloader
megaAll.menu.cpu.atmega1280.BOOT.1280spec.bootloader.high_fuses=0xDA
megaAll.menu.cpu.atmega1280.BOOT.1280spec.bootloader.file=atmega/ATmegaBOOT_168_atmega1280.hex
megaAll.menu.cpu.atmega1280.BOOT.1280spec.upload.speed=57600
megaAll.menu.cpu.atmega1280.BOOT.1280spec.maximum_size=126976
megaAll.menu.cpu.atmega1280.BOOT.stk500v2.maximum_size=126976
megaAll.menu.cpu.atmega1280.BOOT.optiboot.maximum_size=130048

megaAll.menu.cpu.atmega640=ATmega640
megaAll.menu.cpu.atmega640.build.mcu=atmega640
megaAll.menu.cpu.atmega640.build.core=MegaCore
megaAll.menu.cpu.atmega640.build.variant=standard
megaAll.menu.cpu.atmega640.build.board=AVR_ATmega640
megaAll.menu.cpu.atmega640.BOOT.stk500v2.upload.maximum_size=61440
megaAll.menu.cpu.atmega640.BOOT.optiboot.upload.maximum_size=64512

megaAll.menu.cpu.atmega2561=ATmega2561
megaAll.menu.cpu.atmega2561.build.mcu=atmega2561
megaAll.menu.cpu.atmega2561.build.core=MegaCore
megaAll.menu.cpu.atmega2561.build.variant=standard
megaAll.menu.cpu.atmega2561.build.board=AVR_ATmega2561
megaAll.menu.cpu.atmega2561.BOOT.stk500v2.upload.maximum_size=258048
megaAll.menu.cpu.atmega2561.BOOT.optiboot.upload.maximum_size=261120

megaAll.menu.cpu.atmega1281=ATmega1281
megaAll.menu.cpu.atmega1281.build.mcu=atmega1281
megaAll.menu.cpu.atmega1281.build.core=MegaCore
megaAll.menu.cpu.atmega1281.build.variant=standard
megaAll.menu.cpu.atmega1281.build.board=AVR_ATmega1281
megaAll.menu.cpu.atmega1281.BOOT.stk500v2.maximum_size=126976
megaAll.menu.cpu.atmega1281.BOOT.optiboot.maximum_size=130048

##--- CLOCK submenu ---##
# low fuse bits:
# bit7   -- CKDIV8 ==0 divider 1/8 is ON!
# bit6   -- CKOUT  ==0 CLKO is worked to output!
# bit5,4 -- SUT1,0: power on reset timing
# bit3,2,1,0 -- CKSEL3:0:
# -----------------------
# 0xF8..0xFF -- Low power external oscilator
# 0xF6..0xF7 -- Full swing external oscilator
# 0xF4..0xF5 -- Low frequency etxernal oscilator
# 0xF3       -- Internal 128kHz oscilator
# 0xF2       -- Calibrated internal oscilator (8Mhz)
# 0xF0       -- external clock no oscilator
#

megaAll.menu.clock.20ext=20 MHz external
megaAll.menu.clock.20ext.build.f_cpu=20000000L
megaAll.menu.clock.20ext.bootloader.low_fuses=0xf7

megaAll.menu.clock.18ext=18.432 MHz external
megaAll.menu.clock.18ext.build.f_cpu=18432000L
megaAll.menu.clock.18ext.bootloader.low_fuses=0xf7

megaAll.menu.clock.16ext=16 MHz external
megaAll.menu.clock.16ext.build.f_cpu=16000000L
megaAll.menu.clock.16ext.bootloader.low_fuses=0xf7

megaAll.menu.clock.12ext=12 MHz external
megaAll.menu.clock.12ext.build.f_cpu=12000000L
megaAll.menu.clock.12ext.bootloader.low_fuses=0xf7

megaAll.menu.clock.8ext=8 MHz external
megaAll.menu.clock.8ext.build.f_cpu=8000000L
megaAll.menu.clock.8ext.bootloader.low_fuses=0xf7

megaAll.menu.clock.int8=internal 8 MHz
megaAll.menu.clock.int8.build.f_cpu=8000000L
megaAll.menu.clock.int8.bootloader.low_fuses=0xE2

megaAll.menu.clock.int1M=internal 1 MHz
megaAll.menu.clock.int1M.build.f_cpu=1000000L
megaAll.menu.clock.int1M.bootloader.low_fuses=0x62

megaAll.menu.clock.128k=internal 128kHz
megaAll.menu.clock.128k.build.f_cpu=128000L
megaAll.menu.clock.128k.bootloader.low_fuses=0x62

##--- BOD Level submenu ---##
# extended fuse bits only this works:

megaAll.menu.BOD.dis=Disabled
megaAll.menu.BOD.dis.bootloader.extended_fuses=0xff
megaAll.menu.BOD.1v8=1.8v (4Mhz)
megaAll.menu.BOD.1v8.bootloader.extended_fuses=0xfe
megaAll.menu.BOD.2v7=2.7v (8Mhz)
megaAll.menu.BOD.2v7.bootloader.extended_fuses=0xfd
megaAll.menu.BOD.4v3=4.3v (16Mhz)
megaAll.menu.BOD.4v3.bootloader.extended_fuses=0xfc

##--- LTO submenu ---##
# Compiler link time optimization
megaAll.menu.LTO.Os=Disabled
megaAll.menu.LTO.Os.compiler.c.extra_flags=
megaAll.menu.LTO.Os.compiler.c.elf.extra_flags=
megaAll.menu.LTO.Os.compiler.cpp.extra_flags=
megaAll.menu.LTO.Os.ltoarcmd=avr-ar

megaAll.menu.LTO.Os_flto=Enabled
megaAll.menu.LTO.Os_flto.compiler.c.extra_flags=-Wextra -flto
megaAll.menu.LTO.Os_flto.compiler.c.elf.extra_flags=-w -flto
megaAll.menu.LTO.Os_flto.compiler.cpp.extra_flags=-Wextra -flto
megaAll.menu.LTO.Os_flto.ltoarcmd=avr-gcc-ar

##--- BOOT submenu ---##
# High fuse bits this:
# bit7   -- OCDEN   -- ?!?
# bit6   -- JTAGEN  -- JTAG debugging is enable?
# bit5   -- SPIEN   -- SPI loading is enable?
# bit4   -- WDTON   -- watchdog is on always?
# bit3   -- EESAVE  -- protected EEPROM for erase?
# bit2,1 -- BOOTSZ  -- size for bootloader: 00-4096b, 01-2048b, 10-1024b, 11-512b
# bit0   -- BOOTRST -- from where reset start

# only SPI + bootsector=4096
megaAll.menu.BOOT.stk500v2=stk500v2
megaAll.menu.BOOT.stk500v2.bootloader.high_fuses=0xD8
megaAll.menu.BOOT.stk500v2.bootloader.file=stk500v2/stk500boot_v2_mega2560.hex

# optiboot in 1024 sector
megaAll.menu.BOOT.optiboot=Optiboot in 1024 bytes
megaAll.menu.BOOT.optiboot.bootloader.high_fuses=0xD6
megaAll.menu.BOOT.optiboot.bootloader.file=optiboot_flash_256kb/{build.mcu}/optiboot_flash_{build.mcu}_{upload.speed}_{build.f_cpu}.hex

Компилять из него ещё не пробовал, хочется понять будет такое внятно работать или нет?

Вопрос в части таких строк этого описания:

megaAll.menu.cpu.atmega1281.BOOT.stk500v2.maximum_size=126976

где значение "пересекается" для двух опций: типа процессора и типа загрузчика .. ничего не нашел внятного в описании правил построения этого файла.

В меню Ардуино ИДЕ 1.8.5 - вроде бы рисует все верно..

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Фото последнего варианта платы (предыдущую - запортил безвозвратно):

Исследования стабилизатора в этой теме: http://arduino.ru/forum/apparatnye-voprosy/dc-dc-preobrazovatel-na-baze-...

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Запаял плату памяти. При смывании канифоли ацетоно-спиртовым раствором с микросхемы памяти слезла черная краска, и теперь на ней двойная маркировка. Вторая часть частично читается как JAPAN HMM6... -7, потребление платы 9мА .. вроде бы в норме. Покупал как JAPAN HMM625128ALF-5 (HMM625128BLFP-7) так прямо и было как то или иное (как понял).

В принципе, если это таже памать но на 70нсек, то оно "сойдет" и даже без циклов задержки..

Получилось пока так:

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Дорисовал раскладку ножек по контактам (pi mapping):

Сверху (слева на право): I2C, 3 свободных ноги, SPI - слева от питания и UART0, 1, 2 справа от питания.

Левый ряд (сверху вниз): Таймер 4, Таймер 5, Таймер 2, АЦП 8 -15.

Правый ряд (сверху вниз): Таймер 3, Таймер 1, Таймер 0, АЦП 0-7.

Снизу мелкий разъем - 7 PCINT прерываний 9-15 и там же UART3

Самый нижний разъем - интерфейс расширения SRAM вместе с выходами с регистра - защелки адреса (А0-А7).

P.S. Постепенно тестируем плату. Пока ногодрыги на всех ножках работают нормально, плата заливается без вопросов.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Плата МУРК-2560 - вроде бы полностью рабочая. Выкладываю SVG для самостоятельного изготовления ЛУТ-ом:

Слой F_CU (зеркально),                               Слой B_CU (обычно)                                  и расположение деталек и надписей:

Можно копировать прямо отсюда и печатать. По запросу могу предостатвить gerber-файлы, все какие надо. Писать не сюда, а на мыло. Размер платы 56х72мм. Индуктивность L1 изготавливать потоньше (плоскую) и размещать поверх диода D1

По номиналам преобразователя на базе RT8289: входную и выходную емкость крайне желательно собирать из нескольких конденсаторов, можно обыкновенную керамику в т.ч. из разных номиналов, поскольку ESR зависит от частоты.

Конденсаторы обвязки микросхемы ATmega2560 тут тоже СБОРНЫЕ из 2-х: 100нф + 470нф (хорошо показали себя и 680нф). Стабильность питания много выше чем при одном конденсаторе в каждом узле обвязки. Рекомендую.

И ещё: Боковые питающие разъемы подключаются через "перемычки" к этому стабилизатору. Это на случай, если надо силовые элементы питать отдельно от интерфейсного разьема (верхнего), микроконтроллера и платы памяти.. (а вдруг).

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

В общем, в этой теме есть всё необходимое для домашнего повторения и настройки программирования расширенной памяти через компилятор.

Как только соберу этот бутерброд окончательно выложу итоговые фотки и на этом проект можно будет считать завершенным. :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Итого получился вот такой вот "бутерброд", можно пилить экран с кнопками и втискивать в лего детальки:

Возможно стоит перепаять транзисторы КТ3102Б на какие-нить SMD варианты, а то торчат сильно.. :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

В общем, удалось ужаться в размер 56х88мм (7х11 лего дырок), на что сын сказал "здорово".

Вариант новой компоновки платы:

Похоже это окончательный вариант. Кликабельно. Все выводы сдвоены, внутренние для установки разъема "мама" вверх для подключения доп. плат (драйвера моторов, гироскопы, плата управления с дисплеем), а внешние - для установки строенных планок (подключение по типу серводвигателя) - "вбок", кроме правого (по рисунку) разъема под внешнюю память. Если "сервы вбок" не требуется, то тоже можно не устанавливать, но в таком разе будет маловато выводов по земле и питанию.

Оставшееся место заткнул регистром расширения адреса (по даташиту), можно не устанавливать или с ним, тупо втыкать микросхему памяти до 64кбайт, прямо в разьем расширения (все сигналы есть)

Разведу - отдам в jlpcb на изготовление..

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Предварительно развел вот такой вариант платы 56х88мм (кликабельно):

Ярко выделена земля, которой уделил особое внимание: "чистая земля АЦП" разведена отдельно и подключается к общей земле в одном месте. Все проводки АЦП входов перемежаются этой чистой землей для снижения перекрестных помех. Также отдельно разведена чистая земля для кварца. Выводы резонатора по возможности сделаны одинаковой длины.

Разводка ещё без площадной заливки землей и питанием, без выдержки толщины силовых проводов. Это - "потом", после замечаний..

На пустое место платы воткнул расширительный регистр адреса, соответственно мелкие микросхемы памяти до 64 килобайт можно подключать "напрямую" к контактам расширительного разьема (правый).

Настоятельно прошу критики, ибо не спец. по разводке.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

В общем, сделал так (кликабельно). Плата вместе с боковыми плашками расширительного шилда:

Вечером в пятницу отправил на jlpcb.com, уже в субботу получил положительный отклик "можем такое сделать (10шт за 2 бакса)", оплатил во второй половине дня субботы и уже сегодня получил трек доставки .. слов нет, какое "гадство". :)

P.S. Платы приехали аж 24.08. Почта играла в партизан, пока не пришло уведомление от JLCPCB.com на почту.. визуальный осмотр "5 баллов" (ничего крамольного не нашел). Платы забрал с почты только сегодня (28.08).

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Плата из поста №80 в окончательном виде "Ардуино как Лего". Оси и подпорки - исключительно для фотки. Общий вес с аккумуляторным блоком 3S 18650 (150гр) составил 245гр. :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Собрал в одном посту всё, что необходимо доработать и/или дополнить в Ардуино ИДЕ, чтобы удобно общаться с расширенной памятью:

1. Добавление objdump в список шаблонов исполнения в platform.txt, тут под Линукс, под винду есть ссыль выше:

1а) добавляем опции для objdump. Файл <каталог с ИДЕ>/hardware/arduino/avr/platform.txt, секция "AVR compile variables"

compiler.objdump.cmd=avr-objdump.sh
compiler.objdump.flags={compiler.path} {build.path}/{build.project_name}.elf {build.path}/{build.project_name}.lst

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

#compiler.c.flags=-c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects
compiler.c.flags=-c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD
#compiler.c.elf.flags={compiler.warning_flags} -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections
compiler.c.elf.flags={compiler.warning_flags} -Os -Wl,--gc-sections
#compiler.S.flags=-c -g -x assembler-with-cpp -flto -MMD
compiler.S.flags=-c -g -x assembler-with-cpp
#compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -flto
compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -std=gnu++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD

1в) В этом же файле, далее в секции AVR compile patterns добавляем хук вызова objdump после Create output files (.eep and .hex):

## POST objcopy: make objdump too:
recipe.hooks.objcopy.postobjcopy.1.pattern="{compiler.path}{compiler.objdump.cmd}" {compiler.objdump.flags}

1г) В папке <каталог с ИДЕ>/hardware/tool/avr/bin создаем файл с названием avr-objdump.sh и содержимым:

#! /bin/sh
$1avr-objdump -h -S $2 > $3

.. и если надо, меняем ему владельца и даем права на исполнение, типовыми chown,chmod ..

Собственно тут всё - после компиляции/заливки в папке /tmp/build_xxx/ можно будет обнаружить файлик с расширением *.lst - он и есть листинг всей сборки.

2. Доработка настроек ИДЕ для работы с этой и др. платами с расширенной памятью.

2а) если был пропущен п.1б, то тут ему самое место..

2б) В начало файла <каталог с ИДЕ>/hardware/arduino/avr/boards.txt , после menu.cpu=Processor вставляем это:

##-- описание новых пунктов меню - в самое начало файла boards.txt:
menu.BOARD=board subtype
menu.clock=Clock cpu/board
menu.BOD=BOD
menu.LTO=Compiler LTO
menu.BOOT=BOOT options
##-- собственно сборка для всех "мег" совместимой серии:

##############################################################

megaAll.name=*** ATmega640/1280/1281/2560/2561 ***

###--- common settings for all boards and MCU ---###
megaAll.upload.tool=avrdude
megaAll.upload.speed=115200
megaAll.upload.protocol=wiring

megaAll.bootloader.tool=avrdude
megaAll.bootloader.unlock_bits=0x3F
megaAll.bootloader.lock_bits=0x0F

megaAll.build.core=arduino

##--- LTO submenu ---##
# Compiler link time optimization
megaAll.menu.LTO.Os=Disabled
megaAll.menu.LTO.Os.compiler.c.extra_flags=
megaAll.menu.LTO.Os.compiler.c.elf.extra_flags=
megaAll.menu.LTO.Os.lto_elf_flags=
megaAll.menu.LTO.Os.compiler.S.flags=-c -g -x assembler-with-cpp
megaAll.menu.LTO.Os.compiler.cpp.extra_flags=
megaAll.menu.LTO.Os.ltoarcmd=avr-ar

megaAll.menu.LTO.Os_flto=Enabled
megaAll.menu.LTO.Os_flto.compiler.c.extra_flags=-Wextra -flto
megaAll.menu.LTO.Os_flto.compiler.c.elf.extra_flags=-w -flto
megaAll.menu.LTO.Os_flto.lto_elf_flags=-w -flto
megaAll.menu.LTO.Os_flto.compiler.S.flags=-c -g -x assembler-with-cpp -flto
megaAll.menu.LTO.Os_flto.compiler.cpp.extra_flags=-Wextra -flto
megaAll.menu.LTO.Os_flto.ltoarcmd=avr-gcc-ar

##--- board selector submenu ---##
megaAll.menu.BOARD.arduino2560=Arduino Mega 2560 (common)
megaAll.menu.BOARD.arduino2560.upload.maximum_data_size=8192
megaAll.menu.BOARD.arduino2560.build.variant=mega
megaAll.menu.BOARD.arduino2560.build.board=AVR_MEGA2560

megaAll.menu.BOARD.megaADK=Arduino Mega ADK
megaAll.menu.BOARD.megaADK.upload.maximum_data_size=8192
megaAll.menu.BOARD.megaADK.build.variant=mega
megaAll.menu.BOARD.megaADK.build.board=AVR_ADK

megaAll.menu.BOARD.esram32=with ext.SRAM 32 kbytes
megaAll.menu.BOARD.esram32.upload.maximum_data_size=32256
megaAll.menu.BOARD.esram32.build.variant=mega
megaAll.menu.BOARD.esram32.build.board=AVR_MEGA2560
megaAll.menu.BOARD.esram32.compiler.c.elf.extra_flags= {lto_elf_flags} -Wl,--defsym=__heap_start=0x802200,--defsym=__heap_end=0x807fff

megaAll.menu.BOARD.esram64=with ext.SRAM 64 kbytes
megaAll.menu.BOARD.esram64.upload.maximum_data_size=65024
megaAll.menu.BOARD.esram64.build.variant=mega
megaAll.menu.BOARD.esram64.build.board=AVR_MEGA2560
megaAll.menu.BOARD.esram64.compiler.c.elf.extra_flags={lto_elf_flags} -Wl,--defsym=__heap_start=0x802200,--defsym=__heap_end=0x80ffff

megaAll.menu.BOARD.esram5=MYPK-xxx with ext.SRAM 512kbytes
megaAll.menu.BOARD.esram5.upload.maximum_data_size=32256
megaAll.menu.BOARD.esram5.build.variant=sram
megaAll.menu.BOARD.esram5.build.board=AVR_MEGA2560
megaAll.menu.BOARD.esram5.compiler.c.elf.extra_flags={lto_elf_flags} -T{build.variant.path}/avr6.x -Wl,--defsym=__heap_start=0x802200,--defsym=__heap_end=0x807fff

##--- CLOCK submenu ---##
# low fuse bits:
# bit7   -- CKDIV8 ==0 divider 1/8 is ON!
# bit6   -- CKOUT  ==0 CLKO is worked to output!
# bit5,4 -- SUT1,0: power on reset timing
# bit3,2,1,0 -- CKSEL3:0:
# -----------------------
# 0xF8..0xFF -- Low power external oscilator
# 0xF6..0xF7 -- Full swing external oscilator
# 0xF4..0xF5 -- Low frequency etxernal oscilator
# 0xF3       -- Internal 128kHz oscilator
# 0xF2       -- Calibrated internal oscilator (8Mhz)
# 0xF0       -- external clock no oscilator
#

megaAll.menu.clock.20ext=20 MHz external
megaAll.menu.clock.20ext.build.f_cpu=20000000L
megaAll.menu.clock.20ext.bootloader.low_fuses=0xf7

megaAll.menu.clock.18ext=18.432 MHz external
megaAll.menu.clock.18ext.build.f_cpu=18432000L
megaAll.menu.clock.18ext.bootloader.low_fuses=0xf7

megaAll.menu.clock.16ext=16 MHz external
megaAll.menu.clock.16ext.build.f_cpu=16000000L
megaAll.menu.clock.16ext.bootloader.low_fuses=0xf7

megaAll.menu.clock.12ext=12 MHz external
megaAll.menu.clock.12ext.build.f_cpu=12000000L
megaAll.menu.clock.12ext.bootloader.low_fuses=0xf7

megaAll.menu.clock.8ext=8 MHz external
megaAll.menu.clock.8ext.build.f_cpu=8000000L
megaAll.menu.clock.8ext.bootloader.low_fuses=0xf7

megaAll.menu.clock.int8=internal 8 MHz
megaAll.menu.clock.int8.build.f_cpu=8000000L
megaAll.menu.clock.int8.bootloader.low_fuses=0xE2

megaAll.menu.clock.int1M=internal 1 MHz
megaAll.menu.clock.int1M.build.f_cpu=1000000L
megaAll.menu.clock.int1M.bootloader.low_fuses=0x62

megaAll.menu.clock.128k=internal 128kHz
megaAll.menu.clock.128k.build.f_cpu=128000L
megaAll.menu.clock.128k.bootloader.low_fuses=0x62

##--- BOD Level submenu ---##
# extended fuse bits only this works:

megaAll.menu.BOD.dis=Disabled
megaAll.menu.BOD.dis.bootloader.extended_fuses=0xff
megaAll.menu.BOD.1v8=1.8v (4Mhz)
megaAll.menu.BOD.1v8.bootloader.extended_fuses=0xfe
megaAll.menu.BOD.2v7=2.7v (8Mhz)
megaAll.menu.BOD.2v7.bootloader.extended_fuses=0xfd
megaAll.menu.BOD.4v3=4.3v (16Mhz)
megaAll.menu.BOD.4v3.bootloader.extended_fuses=0xfc
#megaAll.bootloader.extended_fuses=0xfc

##--- BOOT submenu ---##
# High fuse bits this:
# bit7   -- OCDEN   -- ?!?
# bit6   -- JTAGEN  -- JTAG debugging is enable?
# bit5   -- SPIEN   -- SPI loading is enable?
# bit4   -- WDTON   -- watchdog is on always?
# bit3   -- EESAVE  -- protected EEPROM for erase?
# bit2,1 -- BOOTSZ  -- size for bootloader: 00-4096b, 01-2048b, 10-1024b, 11-512b
# bit0   -- BOOTRST -- from where reset start

# only SPI + bootsector=4096
megaAll.menu.BOOT.stk500v2=stk500v2
megaAll.menu.BOOT.stk500v2.bootloader.high_fuses=0xD8
megaAll.menu.BOOT.stk500v2.bootloader.file=stk500v2/stk500boot_v2_mega2560.hex

# optiboot in 1024 sector
megaAll.menu.BOOT.optiboot=Optiboot in 1024 bytes
megaAll.menu.BOOT.optiboot.bootloader.high_fuses=0xD6
megaAll.menu.BOOT.optiboot.bootloader.file=optiboot_flash_256kb/{build.mcu}/optiboot_flash_{build.mcu}_{upload.speed}_{build.f_cpu}.hex

##--- CPU submenu ---
megaAll.menu.cpu.atmega2560=ATmega2560
megaAll.menu.cpu.atmega2560.build.core=arduino
megaAll.menu.cpu.atmega2560.build.board=AVR_ATmega2560
megaAll.menu.cpu.atmega2560.build.mcu=atmega2560
megaAll.menu.BOOT.stk500v2.menu.cpu.atmega2560.upload.maximum_size=258048
megaAll.menu.BOOT.optiboot.menu.cpu.atmega2560.upload.maximum_size=261120

# special for 1280 arduino loader
megaAll.menu.cpu.atmega1280=ATmega1280
megaAll.menu.cpu.atmega1280.BOARD.mega2560.build.board=AVR_MEGA
megaAll.menu.BOOT.1280spec.menu.cpu.atmega1280=mega1280 arduino bootloader
megaAll.menu.BOOT.1280spec.menu.cpu.atmega1280.bootloader.high_fuses=0xDA
megaAll.menu.BOOT.1280spec.menu.cpu.atmega1280.bootloader.file=atmega/ATmegaBOOT_168_atmega1280.hex
megaAll.menu.BOOT.1280spec.menu.cpu.atmega1280.upload.speed=57600
megaAll.menu.BOOT.1280spec.menu.cpu.atmega1280.maximum_size=126976
megaAll.menu.BOOT.stk500v2.menu.cpu.atmega1280.maximum_size=126976
megaAll.menu.BOOT.optiboot.menu.cpu.atmega1280.maximum_size=130048
megaAll.menu.cpu.atmega1280.build.mcu=atmega1280

megaAll.menu.cpu.atmega640=ATmega640
megaAll.menu.cpu.atmega640.build.core=MegaCore
megaAll.menu.cpu.atmega640.build.variant=standard
megaAll.menu.cpu.atmega640.build.board=AVR_ATmega640
megaAll.menu.BOOT.stk500v2.menu.cpu.atmega640.upload.maximum_size=61440
megaAll.menu.BOOT.optiboot.menu.cpu.atmega640.upload.maximum_size=64512
megaAll.menu.cpu.atmega640.build.mcu=atmega640

megaAll.menu.cpu.atmega2561=ATmega2561
megaAll.menu.cpu.atmega2561.build.core=MegaCore
megaAll.menu.cpu.atmega2561.build.variant=standard
megaAll.menu.cpu.atmega2561.build.board=AVR_ATmega2561
megaAll.menu.BOOT.stk500v2.menu.cpu.atmega2561.upload.maximum_size=258048
megaAll.menu.BOOT.optiboot.menu.cpu.atmega2561.upload.maximum_size=261120
megaAll.menu.cpu.atmega2561.build.mcu=atmega2561

megaAll.menu.cpu.atmega1281=ATmega1281
megaAll.menu.cpu.atmega1281.build.core=MegaCore
megaAll.menu.cpu.atmega1281.build.variant=standard
megaAll.menu.cpu.atmega1281.build.board=AVR_ATmega1281
megaAll.menu.BOOT.stk500v2.menu.cpu.atmega1281.maximum_size=126976
megaAll.menu.BOOT.optiboot.menu.cpu.atmega1281.maximum_size=130048
megaAll.menu.cpu.atmega1281.build.mcu=atmega1281

2в) в папке <каталог с ИДЕ>/hardware/arduino/avr/variants создаем папку sram и копируем в ней файлик <каталог с ИДЕ>/hardware/arduino/avr/variants/mega/pins_arduino.h

2г) создаем там же файлик <каталог с ИДЕ>/hardware/arduino/avr/variants/sram/avr6.x с таким вот содержимым:

/* Default linker script, for normal executables */
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
OUTPUT_ARCH(avr:6)
MEMORY
{
  text       (rx)   : ORIGIN = 0, LENGTH = 1024K
  data       (rw!x) : ORIGIN = 0x800200, LENGTH = 8K
  wndCommon  (rw!x) : ORIGIN = 0x802200, LENGTH = 32K-0x2200
  wndLow     (rw!x) : ORIGIN = 0x808000, LENGTH = 16K
  wndHigh    (rw!x) : ORIGIN = 0x80C000, LENGTH = 16K
  eeprom     (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
  fuse       (rw!x) : ORIGIN = 0x820000, LENGTH = 1K
  lock       (rw!x) : ORIGIN = 0x830000, LENGTH = 1K
  signature  (rw!x) : ORIGIN = 0x840000, LENGTH = 1K
}

SECTIONS
{
  /* Read-only sections, merged into text segment: */
  .hash          : { *(.hash)		}
  .dynsym        : { *(.dynsym)		}
  .dynstr        : { *(.dynstr)		}
  .gnu.version   : { *(.gnu.version)	}
  .gnu.version_d : { *(.gnu.version_d)	}
  .gnu.version_r : { *(.gnu.version_r)	}
  .rel.init      : { *(.rel.init)	}
  .rela.init     : { *(.rela.init)	}
  .rel.text      :
    {
      *(.rel.text)
      *(.rel.text.*)
      *(.rel.gnu.linkonce.t*)
    }
  .rela.text     :
    {
      *(.rela.text)
      *(.rela.text.*)
      *(.rela.gnu.linkonce.t*)
    }
  .rel.fini      : { *(.rel.fini)	}
  .rela.fini     : { *(.rela.fini)	}
  .rel.rodata    :
    {
      *(.rel.rodata)
      *(.rel.rodata.*)
      *(.rel.gnu.linkonce.r*)
    }
  .rela.rodata   :
    {
      *(.rela.rodata)
      *(.rela.rodata.*)
      *(.rela.gnu.linkonce.r*)
    }
  .rel.data      :
    {
      *(.rel.data)
      *(.rel.data.*)
      *(.rel.gnu.linkonce.d*)
    }
  .rela.data     :
    {
      *(.rela.data)
      *(.rela.data.*)
      *(.rela.gnu.linkonce.d*)
    }
  .rel.ctors     : { *(.rel.ctors)	}
  .rela.ctors    : { *(.rela.ctors)	}
  .rel.dtors     : { *(.rel.dtors)	}
  .rela.dtors    : { *(.rela.dtors)	}
  .rel.got       : { *(.rel.got)	}
  .rela.got      : { *(.rela.got)	}
  .rel.bss       : { *(.rel.bss)	}
  .rela.bss      : { *(.rela.bss)	}
  .rel.plt       : { *(.rel.plt)	}
  .rela.plt      : { *(.rela.plt)	}

  /* Internal text space or external memory.  */
  .text   :
  {
    *(.vectors)
    KEEP(*(.vectors))
    /* For data that needs to reside in the lower 64k of progmem.  */
     *(.progmem.gcc*)
    /* PR 13812: Placing the trampolines here gives a better chance
       that they will be in range of the code that uses them.  */
    . = ALIGN(2);
     __trampolines_start = . ;
    /* The jump trampolines for the 16-bit limited relocs will reside here.  */
    *(.trampolines)
    *(.trampolines*)
     __trampolines_end = . ;
     *(.progmem*)
    . = ALIGN(2);
    /* For future tablejump instruction arrays for 3 byte pc devices.
       We don't relax jump/call instructions within these sections.  */
    *(.jumptables)
    *(.jumptables*)
    /* For code that needs to reside in the lower 128k progmem.  */
    *(.lowtext)
    *(.lowtext*)
     __ctors_start = . ;
     *(.ctors)
     __ctors_end = . ;
     __dtors_start = . ;
     *(.dtors)
     __dtors_end = . ;
    KEEP(SORT(*)(.ctors))
    KEEP(SORT(*)(.dtors))
    /* From this point on, we don't bother about wether the insns are below or above the 16 bits boundary.  */
    *(.init0)  /* Start here after reset.  */
    KEEP (*(.init0))
    *(.init1)
    KEEP (*(.init1))
    *(.init2)  /* Clear __zero_reg__, set up stack pointer.  */
    KEEP (*(.init2))
    *(.init3)
    KEEP (*(.init3))
    *(.init4)  /* Initialize data and BSS.  */
    KEEP (*(.init4))
    *(.init5)
    KEEP (*(.init5))
    *(.init6)  /* C++ constructors.  */
    KEEP (*(.init6))
    *(.init7)
    KEEP (*(.init7))
    *(.init8)
    KEEP (*(.init8))
    *(.init9)  /* Call main().  */
    KEEP (*(.init9))
    *(.text)
    . = ALIGN(2);
     *(.text.*)
    . = ALIGN(2);
    *(.fini9)  /* _exit() starts here.  */
    KEEP (*(.fini9))
    *(.fini8)
    KEEP (*(.fini8))
    *(.fini7)
    KEEP (*(.fini7))
    *(.fini6)  /* C++ destructors.  */
    KEEP (*(.fini6))
    *(.fini5)
    KEEP (*(.fini5))
    *(.fini4)
    KEEP (*(.fini4))
    *(.fini3)
    KEEP (*(.fini3))
    *(.fini2)
    KEEP (*(.fini2))
    *(.fini1)
    KEEP (*(.fini1))
    *(.fini0)  /* Infinite loop after program termination.  */
    KEEP (*(.fini0))
     _etext = . ;
  }  > text

  .data :
  {
     PROVIDE (__data_start = .) ;
    /* --gc-sections will delete empty .data. This leads to wrong start
       addresses for subsequent sections because -Tdata= from the command
       line will have no effect, see PR13697.  Thus, keep .data  */
    KEEP (*(.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   : AT (ADDR (.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 = . ;
     PROVIDE (__heap_start = .) ;
  }  > data

  /* Window page segments for extSRAM as BSS only! not initialized, not loaded to elf! */
  .cpage ORIGIN(wndCommon) (NOLOAD) : { *(.cpage) } > wndCommon

  .lpage0  ORIGIN(wndLow) (NOLOAD) : { *(.lpage0)  } > wndLow
  .lpage1  ORIGIN(wndLow) (NOLOAD) : { *(.lpage1)  } > wndLow
  .lpage2  ORIGIN(wndLow) (NOLOAD) : { *(.lpage2)  } > wndLow
  .lpage3  ORIGIN(wndLow) (NOLOAD) : { *(.lpage3)  } > wndLow
  .lpage4  ORIGIN(wndLow) (NOLOAD) : { *(.lpage4)  } > wndLow
  .lpage5  ORIGIN(wndLow) (NOLOAD) : { *(.lpage5)  } > wndLow
  .lpage6  ORIGIN(wndLow) (NOLOAD) : { *(.lpage6)  } > wndLow
  .lpage7  ORIGIN(wndLow) (NOLOAD) : { *(.lpage7)  } > wndLow
  .lpage8  ORIGIN(wndLow) (NOLOAD) : { *(.lpage8)  } > wndLow
  .lpage9  ORIGIN(wndLow) (NOLOAD) : { *(.lpage9)  } > wndLow
  .lpage10 ORIGIN(wndLow) (NOLOAD) : { *(.lpage10) } > wndLow
  .lpage11 ORIGIN(wndLow) (NOLOAD) : { *(.lpage11) } > wndLow
  .lpage12 ORIGIN(wndLow) (NOLOAD) : { *(.lpage12) } > wndLow
  .lpage13 ORIGIN(wndLow) (NOLOAD) : { *(.lpage13) } > wndLow
  .lpage14 ORIGIN(wndLow) (NOLOAD) : { *(.lpage14) } > wndLow
  .lpage15 ORIGIN(wndLow) (NOLOAD) : { *(.lpage15) } > wndLow

  .hpage0  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage0)  } > wndHigh
  .hpage1  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage1)  } > wndHigh
  .hpage2  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage2)  } > wndHigh
  .hpage3  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage3)  } > wndHigh
  .hpage4  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage4)  } > wndHigh
  .hpage5  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage5)  } > wndHigh
  .hpage6  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage6)  } > wndHigh
  .hpage7  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage7)  } > wndHigh
  .hpage8  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage8)  } > wndHigh
  .hpage9  ORIGIN(wndHigh) (NOLOAD) : { *(.hpage9)  } > wndHigh
  .hpage10 ORIGIN(wndHigh) (NOLOAD) : { *(.hpage10) } > wndHigh
  .hpage11 ORIGIN(wndHigh) (NOLOAD) : { *(.hpage11) } > wndHigh
  .hpage12 ORIGIN(wndHigh) (NOLOAD) : { *(.hpage12) } > wndHigh
  .hpage13 ORIGIN(wndHigh) (NOLOAD) : { *(.hpage13) } > wndHigh
  .hpage14 ORIGIN(wndHigh) (NOLOAD) : { *(.hpage14) } > wndHigh
  .hpage15 ORIGIN(wndHigh) (NOLOAD) : { *(.hpage15) } > wndHigh

  .eeprom  :
  {
    /* See .data above...  */
    KEEP(*(.eeprom*))
     __eeprom_end = . ;
  }  > eeprom
  .fuse  :
  {
    KEEP(*(.fuse))
    KEEP(*(.lfuse))
    KEEP(*(.hfuse))
    KEEP(*(.efuse))
  }  > fuse
  .lock  :
  {
    KEEP(*(.lock*))
  }  > lock
  .signature  :
  {
    KEEP(*(.signature*))
  }  > signature
  /* Stabs debugging sections.  */
  .stab 0 : { *(.stab) }
  .stabstr 0 : { *(.stabstr) }
  .stab.excl 0 : { *(.stab.excl) }
  .stab.exclstr 0 : { *(.stab.exclstr) }
  .stab.index 0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment 0 : { *(.comment) }
  .note.gnu.build-id : { *(.note.gnu.build-id) }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the beginning
     of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end ) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  /* SGI/MIPS DWARF 2 extensions */
  .debug_weaknames 0 : { *(.debug_weaknames) }
  .debug_funcnames 0 : { *(.debug_funcnames) }
  .debug_typenames 0 : { *(.debug_typenames) }
  .debug_varnames  0 : { *(.debug_varnames) }
  /* DWARF 3 */
  .debug_pubtypes 0 : { *(.debug_pubtypes) }
  .debug_ranges   0 : { *(.debug_ranges) }
  /* DWARF Extension.  */
  .debug_macro    0 : { *(.debug_macro) }
}

.. собственно, если ничего не забыл, то это всё. В ИДЕ появится опция выбора "*** ATmega640/1280/1281/2560/2561 ***" с расширенным меню и возможностью управлять выбором процессора из семейства, частотой камня, уровнем Bodlevel, включением опции LTO и типом платы: с памятью, без памяти и какой памятью..

Ну и под занавес, тестовый пример:

/**
 * Extended Memory Sram (ems)
 *
 * !!! ВНИМАНИЕ: требует специального скрипта для линковщика с описанием секций RAM
 *
 * Тестовый код для управления внешней SRAM 512кбайт.
 * Организация SRAM:
 * PORTA -- AD0..7 совмещенная шина адреса/данных стробируется сигналом ALE ()
 * регистры управления:
 * XMCRA (0x74):
 *    7     6     5     4     3      2      1      0
 *   SRE, SRL2, SRL1, SRL0, SRW11, SRW10, SRW01, SRW00
 *
 * SRE - enable xmem, SRL2:0 - lower/upper sectors {0,1:all upper, 2-7:0x4..0xE upper},
 * SRW1x - wait states for upper, SRW0x - wait states for lower
 *
 * XMCRB (0x75):
 *     7          2     1     0
 *   XMBK, ххх, XMM2, XMM1, XMM0
 *
 * XMBK - bus keeper enable, XMMx - Mask High Adress lines {0-all;1-PC7;2-PC6,7;..7-only 8 bit address)
 *
 * Регистр номеров страниц: старшая тетрада - 0..15 верхнее окно 0xC000, младшая тетрада - 0..15 нижнее окно 0x8000
 * Запись в регистр страниц через PORTA при !RD = !WR = 0, то есть номер проходит в регистр, если оба сигнала LOW
 * и защелкивается при записи HIGH в любой из пинов !RD, !WR.
 *
 * @author Arhat109
 */

// полезный, удобный макрос:
#define makeByte(h,l) ((((h)<<4)&0xF0)|((l)&0x0F))

// определяем где и что находится у микроконтроллера (ATmega2560):
// 19 линий интерфейса внешней SRAM:
#define EMS_ALE         PG2
#define EMS_RD          PG1
#define EMS_WR          PG0
#define EMS_PORT_BUS    PORTG
#define EMS_DDR_BUS     DDRG
#define EMS_PORT_AD     PORTA
#define EMS_DDR_AD      DDRA
#define EMS_PORT_A      PORTC

// последние адреса окон памяти и размеры окон:
#define EMS_OWN_END     (0x21FF)
#define EMS_COMMON_END  (0x7FFF)
#define EMS_LP_END      (0xBFFF)
#define EMS_HP_END      (0xFFFF)

#define SIZE_COMMONS (EMS_COMMON_END - EMS_OWN_END)
#define SIZE_LOWS    (EMS_LP_END - EMS_COMMON_END)
#define SIZE_HIGHS   (EMS_HP_END - EMS_LP_END)

// Доступные секции памяти (удобства для), см. спец. секции в расширении файла линковщика:
// На самом деле есть только 4 типа адресов (окон у процессора):
// внутренняя память, общий блок до 32кбайт и нижние/верхние окна для подключения страниц..
// без указания страницы - размещается во внутренеей памяти, секции .data, .bss, .. @see avr6.x
// EMS_COMMON -- общий блок с конца internal до 32768-го байта
// EMS_LOW()  -- [0,15] -- размещение в "нижних" сегментах по 16кб с адреса 0x8000
// EMS_HIGH() -- [0,15] -- размещение в "верхних" сегментах по 16кб с адреса 0xC000
// Внимательно! последние страницы (15) - это тот же блок COMMON!
// это можно использовать для работы с экранированным куском в 8кб, через EMS_LOW(15)..
//
#define EMS_COMMON        __attribute__((section(".cpage")))
#define EMS_LOW(pageNum)  __attribute__((section(".lpage" #pageNum)))
#define EMS_HIGH(pageNum) __attribute__((section(".hpage" #pageNum)))

uint8_t emsPages; // копия регистра страниц в нижней SRAM
uint8_t emsWaits; // wait states @see emsOn(_ws);

/** 
 * ТОЛЬКО активация Extended Memory SRAM единым верхним куском без удержания шины
 * + включение упр. сигналов на выход и заодно подтяжка к +5в
 * @param uint8_t _ws -- wait states for interface
 * @time 10t (0.625usec)
 */
#define emsOn(_ws)                                     \
{                                                      \
  emsWaits = (_ws);                                    \
  XMCRA = (1 << SRE) | ((_ws)<<2);                     \
  XMCRB = 0;                                           \
  EMS_DDR_BUS |= (1<<EMS_ALE)|(1<<EMS_RD)|(1<<EMS_WR); \
}

// отключалка интерфейса extSRAM, @time 1t
#define emsOff() (XMCRA = 0)

// =========================== Только сохранение в глобал: ======================== //
// @param uint8_t lp,hp,p

// emsSetLow(),emsSetHigh() -- @time 7t
// emsSetPages() -- 2t
#define emsSetLow(lp)      (emsPages=(emsPages&0xF0) | ((uint8_t)(lp)&0x0F))
#define emsSetHigh(hp)     (emsPages=((uint8_t)(lp)&0xF0) | (emsPages&0x0F))
#define emsSetPages(p)     (emsPages=(uint8_t)(p))

// =========================== Установка И запись страниц: ======================== //
/**
 * Пишем номера страниц блоков low, high в регистр страниц вручную, отключая extSRAM
 * @time 27t (1.4375usec)
 */
void emsWritePages(void)
{
  cli();
  emsOff();                                   //  1t, отключаем интерфейс extSRAM
  EMS_DDR_AD    = 0xFF;                       //  1t, порт А (A/D) "на выход"
  EMS_PORT_AD   = emsPages;                   //  1t, номера страниц в A/D
  EMS_PORT_BUS &= ~((1<<EMS_WR)|(1<<EMS_RD)); //  3t, оба сигнала в LOW уже "на выходе"
  __asm__ __volatile__ ("nop" :::);           //  1t, ждем 1 такт (62.5нсек)
  EMS_PORT_BUS |= ((1<<EMS_WR)|(1<<EMS_RD));  //  3t, оба сигнала в HIGH
  EMS_DDR_AD    = 0;                          //  1t, освобождаем порта А
  emsOn(emsWaits);                            // 10t, включаем интерфейс, восстанавливая тайминги
  sei();                                      // 1t+1t+4t (cli,sei,ret)
}

// @param uint8_t lowPage
// @time 34t
#define emsWriteLow(lowPage) \
{                            \
  emsSetLow(lowPage);        \
  emsWritePages();           \
}

// @param uint8_t highPage
// @time 34t
#define emsWriteHigh(highPage) \
{                              \
  emsSetHigh(highPage);        \
  emsWritePages();             \
}

/**
 * Проверяет заданный буфер на совпадение с шаблоном,
 * в случае расхождения вызывает callback() и возвращает 1
 * прерывает работу, если callback() возвращает не 0.
 * 
 * @param void (*)callback(uint16_t _addr, uint8_t _pattern, uint8_t _readed)
 * @return count summary errors
 */
uint16_t emsMemtest(
  uint8_t * _buffer,  // буфер поиска расхождения
  uint16_t  _size,    // размер буфера
  uint8_t   _pattern, // искомый образец
  uint8_t (*callback)(uint8_t *_addr, uint8_t _pattern, uint8_t _readed) // нашел тут это!
){
  uint16_t res = 0;

  do{
    uint8_t tmp = *_buffer;

    if( tmp != _pattern ){
      res++;
      if( callback(_buffer, _pattern, tmp) ) return res;
    }
    _buffer++;
  }while( --_size > 0 );

  return res;
}

// =========================== ТЕСТОВЫЙ ПРИМЕР ТУТ: ======================== //

// объявляем 3 массива в разных окнах:

uint8_t commons[SIZE_COMMONS] EMS_COMMON;  // 24064 байт от внутренней SRAM в первых 32кбайтах
uint8_t lows[SIZE_LOWS]       EMS_LOW(0);  // 16кбайт от 32к до 48к
uint8_t highs[SIZE_HIGHS]     EMS_HIGH(0); // 16кбайт от 48к до 64к

uint8_t patterns[4] = {0xFF, 0x00, 0xAA, 0x55}; // образцы записи в память

#define MAX_PAGES 3
struct{
  uint8_t * address;
  uint16_t  size;
} pages[MAX_PAGES] = {{commons, SIZE_COMMONS}, {lows, SIZE_LOWS}, {highs, SIZE_HIGHS}};

/**
 * callback() для вывода ошибки сохранения на монитор (и прервать работу)
 */
uint8_t testError(uint8_t *_addr, uint8_t _pattern, uint8_t _readed)
{
  Serial.println();
  Serial.print("ERROR at 0x"); Serial.print((uint16_t)_addr, HEX);
  Serial.print(", pattern="); Serial.print(_pattern, DEC);
  Serial.print(", readed="); Serial.print(_readed, DEC);
  return 0;
}

// =========================== SETUP() ======================== //

void setup()
{
  emsOn(2);
  Serial.begin(115200);
}

void loop()
{
  for(int8_t i=sizeof(patterns); i>=0; --i){
//    memset(commons, patterns[i], SIZE_COMMONS);
//    memset(lows, patterns[i], SIZE_LOWS);
//    memset(highs, patterns[i], SIZE_HIGHS);
    for(int page=0; page<MAX_PAGES; page++){
      Serial.println();
      Serial.print("PAGE="); Serial.print(page, DEC);
      memset(pages[page].address, patterns[i], pages[page].size);
      if(
        emsMemtest(pages[page].address, pages[page].size, patterns[i], testError) != 0
      ){
        Serial.println("..ERROR OCURED..");
      }else{
        Serial.print(" is OK :)");
      }
    }
  }
}

// Скетч использует 2840 байт (1%) памяти устройства. Всего доступно 258048 байт.
// Глобальные переменные используют 283 байт (0%) динамической памяти, оставляя 31973 байт для локальных переменных. Максимум: 32256 байт.

P.S.

Конкретно эта плата (на фото выше) расширенной памяти у меня пока так и не заработала, валит ошибки, как и самая первая больше года назад .. буду смотреть под осцилом "что не так"..

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

@TODO:

1. Требуется проверка правильности boards.txt в части фьюзов остальных процессоров семейства .. у меня в наличии есть только 2560. Делал, списывая с проекта MegaCore, но не уверен что все разобрал верно..

2. Файл линковщика avr6.x содержит прямое указание на размер внутренней SRAM меги. Для использования с младшими моделами, и для расширения работы с серией ATmega128a, имеет смысл доработать boards.txt и avr6.x так, чтобы символ __heap_size определялся по типу процессора (сколько там у него есть своей SRAM) И типу платы (есть ли расширенная память и сколько её) ..

с наскока это сделать не удалось, мне остальные камни как-то без надобности, но для полноты картины - было бы неплохо.

P.S.

Точно также можно переработать boards.txt для разных плат под 328p и прочие камни семейства, заодно расширив возможности по управлению прошивкой и заливкой ..

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

На плате расширения памяти обнаружено большое количество непропаев .. руки из *опы..

Но! Что интересно: на базе макросов из примера легко создается тестовый скетч для .. ручного управления памятью чуть ли не в "секундных" таймингах и .. осцилограф можно заменить .. набором светодиодов (что и сделал). :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Фото платы из поста №83:

По бокам платы и заодно с ней изготовлены боковые планки для расширительных разьемов (пайка к внешнему ряду сигнальных разьемов на плате). Внутренний ряд - под типовые штырьковые разьёмы "мама" для соединения с платами "вверх" или удлиненные "вврех/вниз". Кому что интересно - то и запаиваем. :)

Все надписи на плате - читаемы, все номиналы - подписаны. :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Прозвонил, пропаял плату из поста №84 .. в итоге, 4-й канал мультиплескора оказался "битый". Не держит на своем выходе "1" когда отключен (сигнал по схеме page1). Засада, похоже придется выпаивать.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

В общем, закрываю эту тему на грустной ноте: окончательно тест памяти не прошел, хотя и поменял мультиплексор и в ручном режиме он проходит успешно.

Код тестовых примеров (их тут несколько):

/**
 * Extended Memory Sram (ems)
 *
 * !!! ВНИМАНИЕ: требует специального скрипта для линковщика с описанием секций RAM
 *
 * Тестовый код для управления внешней SRAM 512кбайт.
 * Организация SRAM:
 * PORTA -- AD0..7 совмещенная шина адреса/данных стробируется сигналом ALE
 * регистры управления:
 * XMCRA (0x0074):
 *    7     6     5     4     3      2      1      0
 *   SRE, SRL2, SRL1, SRL0, SRW11, SRW10, SRW01, SRW00
 *
 * SRE - разрешает работу интерфейса,
 * SRL2:0 - граница нижнего/верхнего сегмента (адресного пространства {0,1:all upper, 2-7:0x4000..0xE000 upper},
 * SRW1x - количество доп. тактов ожидания для верхнего сегмента,
 * SRW0x - оно же для нижнего, если он есть.
 *
 * XMCRB (0x0075):
 *     7          2     1     0
 *   XMBK, ххх, XMM2, XMM1, XMM0
 *
 * XMBK - удекрживать данные на шине между тактами и адресом/данных (не переводить в Hz),
 * XMMx - ширина шины адреса {0-all 16бит = 64k;1-PC7 не исп. 15бит 32k; 2-PC6 16k,..7-only 8 bit address без порта C)
 *
 * SRAM512kb имеет дополнительно:
 * 1. Регистр номеров страниц: старшая тетрада - 0..15 верхнее окно 0xC000, младшая тетрада - 0..15 нижнее окно 0x8000
 *    Запись в регистр страниц: вручную, через PORTA при !RD = !WR = 0, то есть номер проходит в регистр, если оба сигнала LOW
 *      и защелкивается при записи HIGH в любой из пинов !RD, !WR или оба сразу.
 *    Чтение регистра страниц - не предусмотрено.
 *    Но из него есть комбинированный вывод 4 бит (0xF, старших или младших), в зависимости от PC7,PC6:00|01=>F, 10=>low, 11=>high;
 *    то есть, младшие 32к адресов (PC7=0) выдают F, а старшие (PC7=1) в зависимости от PC6 младшую или старшую тетраду.
 * 2. Регистр защелка сладшей части адреса. Используется интерфейсом самостоятельно, но можно использовать вручную при дополнительно,
 *    при отключенном интерфейсе: PORTA записывается в регистр при ALE=1 и защелкивается в нем при ALE=0. Этот регистр имеет свои
 *    отдельные выводы на шине расширения памяти, также как регистр страниц.
 *    
 * @author Arhat109
 */

// полезный, удобный макрос: собирает байт из младших полубайтов со сдвигами..
#define makeByte(h,l) (((((uint8_t)(h))<<4)&0xF0)|(((uint8_t)(l))&0x0F))

// определяем где и что находится у микроконтроллера (ATmega2560):
// 19 линий интерфейса внешней SRAM:
#define EMS_ALE         PG2
#define EMS_RD          PG1
#define EMS_WR          PG0
#define EMS_PORT_BUS    PORTG
#define EMS_DDR_BUS     DDRG
#define EMS_PORT_AD     PORTA
#define EMS_DDR_AD      DDRA
#define EMS_PORT_ADR    PORTC
#define EMS_DDR_ADR     DDRC

// последние адреса окон памяти и размеры окон:
// [0-8.5k[ - "own page"(internal SRAM); [8.5k-32k[ - "common page";
// [32k-48k[ - "low page"; [48k-64k[ - "high page".
#define EMS_OWN_END     (0x21FF)
#define EMS_COMMON_END  (0x7FFF)
#define EMS_LP_END      (0xBFFF)
#define EMS_HP_END      (0xFFFF)

#define SIZE_COMMONS (EMS_COMMON_END - EMS_OWN_END)
#define SIZE_LOWS    (EMS_LP_END - EMS_COMMON_END)
#define SIZE_HIGHS   (EMS_HP_END - EMS_LP_END)

// Доступные секции памяти (удобства для), см. спец. секции в расширении файла линковщика:
// На самом деле есть только 4 типа адресов (окон у процессора):
// внутренняя память, общий блок до 32кбайт и нижние/верхние окна для подключения страниц..
// Данные, обьявленные:
// а) без указания страницы - размещается во внутренеей памяти (секции .data, .bss, @see avr6.x):
// б) EMS_COMMON -- в общем блоке от конца internal до 32767-го байта включительно;
// в) EMS_LOW()  -- [0,15] -- размещение в "нижних" сегментах по 16кб с адреса 0x8000
// г) EMS_HIGH() -- [0,15] -- размещение в "верхних" сегментах по 16кб с адреса 0xC000
// Внимательно! последние страницы (15) - это тот же блок что и COMMON,
// но так можно иметь доступ к его младшим адресам, перекрытым внутренней памятью
//
#define EMS_COMMON        __attribute__((section(".cpage")))
#define EMS_LOW(pageNum)  __attribute__((section(".lpage" #pageNum)))
#define EMS_HIGH(pageNum) __attribute__((section(".hpage" #pageNum)))

uint8_t emsPages; // копия регистра страниц в нижней SRAM
uint8_t emsWaits; // количество тактов ожидания интерфейса @see emsOn(_ws);

/** 3t: установка служебных ног интерфейса "на выход" */
#define emsBusOut()      (EMS_DDR_BUS |= (1<<EMS_ALE)|(1<<EMS_RD)|(1<<EMS_WR))

/** 3t: разрешение записи в регистр страницы (интерфейс д.быть отключен!) */
#define emsPagesOpen()   (EMS_PORT_BUS &= ~((1<<EMS_WR)|(1<<EMS_RD)))

/** 3t: защелкивание в регистре страниц значения с шины AD (интерфейс д.быть отключен!) */
#define emsPagesLock()   (EMS_PORT_BUS |= ((1<<EMS_WR)|(1<<EMS_RD)))

/** 
 * ТОЛЬКО активация Extended Memory SRAM единым верхним куском без удержания шины
 * + включение упр. сигналов на выход и заодно подтяжка к +5в
 * 
 * @param uint8_t _ws -- wait states for interface
 * @time 8t(const _ws)/7t(register _ws)
 */
#define emsOn(_ws)                            \
{                                             \
  emsWaits = (_ws);                           \
  XMCRA = (1 << SRE) | (((uint8_t)(_ws))<<2); \
  XMCRB = 0;                                  \
}
/**
 * отключалка интерфейса extSRAM
 * @time 1t
 */
#define emsOff() (XMCRA = 0)

/**
 * Настройка БЕЗ включения интерфейса для setup() или раньше
 * 
 * @param uint8_t _ws -- wait states for interface
 * @time 6t
 */
#define emsSetup()    \
{                     \
  EMS_DDR_AD = 0xFF;  \
  EMS_DDR_ADR = 0xFF; \
  emsBusOut();        \
}

/**
 * =================== Макросы сохранения номера страницы в глобал: ================ //
 * @param uint8_t lp,hp,p
 * @time 7t для emsStoreLow(),emsStoreHigh()
 * @time 2t для emsStorePages()
 */
#define emsStoreLow(lp)      (emsPages=(emsPages&0xF0) | ((uint8_t)(lp)&0x0F))
#define emsStoreHigh(hp)     (emsPages=((uint8_t)(lp)&0xF0) | (emsPages&0x0F))
#define emsStorePages(p)     (emsPages=(uint8_t)(p))

/**
 * =========================== Установка И запись страниц: ======================== //
 * Пишем номера страниц блоков low, high в регистр страниц вручную, отключая extSRAM
 * 
 * @time 31t (1.9375usec)
 */
void emsWritePages(void)
{
  cli();
  emsOff();                         //  1t, отключаем интерфейс extSRAM
  EMS_DDR_AD    = 0xFF;             //  1t, порт А (A/D) "на выход"
  emsPagesOpen();                   //  3t, оба сигнала !RD,!WR в LOW
  EMS_PORT_AD   = emsPages;         //  1t, номера страниц в A/D
  __asm__ __volatile__ ("nop" :::); //  1t, ждем 1 такт (62.5нсек)
  emsPagesLock();                   //  3t, оба сигнала !RD,!WR в HIGH
  EMS_DDR_AD    = 0;                //  1t, освобождаем порта А
  emsOn(emsWaits);                  // 10t, включаем интерфейс, восстанавливая тайминги
  sei();                            // 1t+1t+4t+4t (cli+sei+ret+call)
}

/**
 * Запись в регистр страниц номер low page [0..15]
 * 
 * @param uint8_t lowPage
 * @time 38t
 */
#define emsWriteLow(lowPage) \
{                            \
  emsStoreLow(lowPage);      \
  emsWritePages();           \
}

/**
 * Запись в регистр страниц номер high page [0..15]
 * 
 * @param uint8_t highPage
 * @time 38t
 */
#define emsWriteHigh(highPage) \
{                              \
  emsStoreHigh(highPage);      \
  emsWritePages();             \
}

/**
 * Проверяет заданный буфер на совпадение с шаблоном,
 * в случае расхождения вызывает callback().
 * Прерывает работу, если callback() возвращает не 0.
 * 
 * @param void (*)callback(uint16_t _addr, uint8_t _pattern, uint8_t _readed)
 * @return count summary errors
 */
uint16_t emsMemtest(
  uint8_t * _buffer,  // буфер поиска расхождения
  uint16_t  _size,    // размер буфера
  uint8_t   _pattern, // искомый образец
  uint8_t (*callback)(uint8_t *_addr, uint8_t _pattern, uint8_t _readed) // нашел тут это!
){
  uint16_t res = 0;

  do{
    uint8_t tmp = *_buffer;

    if( tmp != _pattern ){
      res++;
      if( callback(_buffer, _pattern, tmp) ) return res;
    }
    _buffer++;
  }while( --_size > 0 );

  return res;
}

// =========================== ТЕСТ РУЧНОГО УПРАВЛЕНИЯ: ======================== //

/**
 * в loop():
 * Функция медленной и ручной побитной установки значений на шинах для
 * проверки светодиодами работоспосоности пайки и платы в целом..
 * щелкает сигналом ALE для проверки записи в регистр защелки адреса.
 * Также можно проверить работу мультиплексора адреса от PC6,7
 */
void manualTest()
{
  for(uint8_t bit=0; bit<=7; bit++){
    EMS_PORT_BUS |= (1<<EMS_ALE);  // разрешаем запись
    emsPagesOpen();                // открываем регистр страниц на запись
    EMS_PORT_AD = (1<<bit);        // младшая часть адреса в защелку
    EMS_PORT_BUS &= ~(1<<EMS_ALE); // защелкиваем младшую часть адреса (шина AD)
    delay(500);                    // на посмотреть..
    emsPagesLock();                // защелкиваем и в регистр страниц тоже
    EMS_PORT_ADR = (1<<bit);       // старшая часть адреса отдельно
    delay(500);
  }
}
/**
 * Имитация записи/четния SRAM вручную
 */
void manualTest2()
{
  EMS_PORT_ADR = 0; // старшая часть адреса тут не нужна

  for(uint8_t bit=0; bit<=7; bit++){
    EMS_PORT_AD = (1<<bit);        // младшая часть адреса (bit) в защелку
    EMS_PORT_BUS |= (1<<EMS_ALE);  // разрешаем запись адреса
    delay(500);                    // на посмотреть..
    EMS_PORT_BUS &= ~(1<<EMS_ALE); // защелкиваем младшую часть адреса (шина AD)

    EMS_PORT_AD = ~(1<<bit);       // данные на шину (кроме bit)
    EMS_PORT_BUS &= ~(1<<EMS_WR);  // запись
    delay(500);
    EMS_PORT_BUS |= (1<<EMS_WR);   // типа записали

    EMS_PORT_AD = 0;               // гасим все после записи
    delay(1000);

    EMS_PORT_AD = (1<<bit);        // младшая часть адреса снова в защелку
    EMS_PORT_BUS |= (1<<EMS_ALE);  // разрешаем запись адреса
    delay(500);                    // на посмотреть..
    EMS_PORT_BUS &= ~(1<<EMS_ALE); // защелкиваем младшую часть адреса (шина AD)

    EMS_DDR_AD = 0;                // шина AD на ввод
    EMS_PORT_BUS &= ~(1<<EMS_RD);  // чтение
    delay(500);
    EMS_PORT_BUS |= (1<<EMS_RD);   // типа прочли

    EMS_DDR_AD = 0xFF;             // шина AD на вывод
    EMS_PORT_AD = 0;               // гасим все после чтения
    delay(1500);
  }
}

// ============================= Простейший тест: ========================== //
volatile uint8_t *adr;

void simpleTest(void)
{
  uint8_t tmp;

  Serial.println("Simple test started..");
  for( adr=(uint8_t*)(EMS_OWN_END+1); adr<=(uint8_t*)(EMS_OWN_END+10); adr++){
//  for( adr=(uint8_t*)(0x1000); adr<=(uint8_t*)(0x1000+10); adr++){
    *adr = 0xAA;
    tmp = *adr;
    if( tmp != 0xAA ){ Serial.println(tmp, DEC); }
    else             { Serial.println("ok");     }
  }
  Serial.println("Simple test ended");
  do{}while(1);
}

// =========================== ТЕСТОВЫЙ ПРИМЕР ТУТ: ======================== //

// объявляем 3 массива в разных окнах:

uint8_t commons[SIZE_COMMONS] EMS_COMMON;  // 24064 байт от внутренней SRAM в первых 32кбайтах
uint8_t lows[SIZE_LOWS]       EMS_LOW(0);  // 16кбайт от 32к до 48к
uint8_t highs[SIZE_HIGHS]     EMS_HIGH(0); // 16кбайт от 48к до 64к

uint8_t patterns[4] = {0xFF, 0x00, 0xAA, 0x55}; // образцы записи в память

/** собираем из обьявленных массивов пакет для тестирования */
#define MAX_PAGES 3
struct{
  uint8_t * address;
  uint16_t  size;
} pages[MAX_PAGES] = {{commons, SIZE_COMMONS}, {lows, SIZE_LOWS}, {highs, SIZE_HIGHS}};

/**
 * callback() для вывода ошибки сохранения на монитор (и прервать работу)
 */
uint8_t testError(uint8_t *_addr, uint8_t _pattern, uint8_t _readed)
{
  Serial.println();
  Serial.print("ERROR at 0x"); Serial.print((uint16_t)_addr, HEX);
  Serial.print(", pattern="); Serial.print(_pattern, DEC);
  Serial.print(", readed="); Serial.print(_readed, DEC);
  return 0;
}

/**
 * Собственно тест памяти:
 * перебираем образцы, и страницы в пакете, заливаем страницу образцом
 * и проверяем на совпадение с шаблоном
 */
void test(void){
  uint16_t errors;
  
  for(int8_t i=sizeof(patterns); i>=0; --i){
    for(int page=0; page<MAX_PAGES; page++){
      Serial.println();
      Serial.print("PAGE="); Serial.print(page, DEC);
      errors=0;
      memset(pages[page].address, patterns[i], pages[page].size);
      errors = emsMemtest(pages[page].address, pages[page].size, patterns[i], testError);
      if( errors != 0 ){
        Serial.print(" .. ERROR OCURED=");
        Serial.println(errors, DEC);
      }else{
        Serial.println(" .. is OK)");
      }
    }
  }
}

// =========================== SETUP() ======================== //

void setup()
{
//  emsSetup();
  emsOn(0);
  Serial.begin(115200);
}

void loop()
{
//  manualTest();
//  manualTest2();
  simpleTest();
//  test();
}

emsSetup() - настройка пинов для ручного управления в тестах manualTest() и manualTest2(). Они оба проходят нормально, второй тест в память пишет и читает как надо (память - статическая, отрабатывает по 0.5сек вполне нормально), проверялось подключением кучки светодиодов к шине расширения памяти (как на панельках старых ЭВМ).

В simpleTest() закомментированный цикл - заменяет чтение/запись на внутр. SRAM - выдает "ok". А вот замена адресов цикла на внешнюю SRAM - выдает все 10 ошибок чтения/записи с любой задержкой 0..3.

Результат компиляции - смотрел: хоть и коряво, но всё вполне верно. Настройка boards.txt работает нормально, все адреса транслируются куда надо..

Похоже дальше надо смотреть на осцилографе и желательно многолучевом .. у меня такого нет, да и убрано в общем-то всё уже далеко.

 

arduinec
Offline
Зарегистрирован: 01.09.2015
Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Таким способом можно подключать любую параллельную память для работы как с внутренней SRAM через простые объявления данных (массивов, переменных и т.д.). Проблема у меня в том, что не смог пройти даже simpleTest(), хотя "вручную" в память пишется и читается как надо, по крайней мере по 8-и "избранным" адресам.

P.S. посмотрел, конкретно для этой даже особо схему не потребуется перерисовывать. Так, перенести пару ножек из-за разницы корпусов SOP-32 и SOP-28 ..

Кстати, цикл доступа к внешней SRAM у меги 2560 занимает 3 цикла шины, что снижает требования к чипам до 62.5 * 3 = 180нс. Так что имеющиеся 70нсек - что называется "за глаза" и даже без циколов ожидания.

В общем, так и осталось непонятным почему в ручном режиме память пишется и читается (по 8-и избранным адресам "как получилось"), а в нормальном режиме из неё читается .. младший байт адреса. Как буд-то как ALE защелкнул на шине адрес, так он на ней и подвис..

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Достал плату, потестил ещё разок, проверил все тайминги. В общем, схему надо откорректировать:

1. Сигнал ALE подтягивать резистором к питанию - вредно. Резистор лучше убрать;

2. Сигнал CS микросхемы памяти надо посадить на землю, подавать на него сигнал ALE через диод - вредно, резко удлиняется цикл чтения и память перестает работать даже 3-я циклами ожидания.

С такими изменениями - память работает и даже без циклов ожидания, по крайней мере первые 32к (которые в общем-то почти последние в самой памяти), контроллер страниц ещё досконально не проверял, но там "дурить" особо нечему.

Только программно надо помнить о том, что при записи номера страниц в регистр памяти сигнал WR надо теперь устанавливать первым, чтобы перевести ноги данных в третье состояние раньше, чем на шину выйдут номера страниц из микроконтроллера. Когда оба сигнала WR,RD в нуле - микросхема памяти переводит свою шину также в третье состояние, что и решает проблему отказа от соединения CS и ALE.

В общем, на этом всё. Схема - вполне рабочая, ПО - тоже. Заливал в т.ч. и с настрокой на внутренний генератор 8Мгц - работает.

P.S. Дотестил диспетчер страниц памяти. На схему надо добавить резистор с базы на землю у Q1 не более 4.7к-9.1к, иначе он не закрывается полноценно. Резистор R14 2.4к стоит уменьшить до 1к. В таком варианте, пауза для записи номера страницы получается около 45-90 тактов ЦПУ на 16Мгц. Чем меньше резистор с базы на землю - тем быстрее запирается этот транзистор. В целом некритично, поскольку это механизм переключения страниц. В остальном - плата полностью рабочая.

Вот теперь - точно всё. :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Блин, не всё. :)

В общем, ногой CS микросхемы памяти, таки надо управлять. Дело в том, что при записи номеров страниц в регистр страниц тут использован факт одновременно низкого уровня на выходах WR и RD, а поскольку на шине адреса SRAM все равно "какой-то" адрес получается выставлен (защелка младших адресов - что-то помнит с предыдущего обращения, а старшая часть адреса порт "С" - тоже или в нулях или в высоком состоянии), то снятие сигналов WR=RD=1 .. приводит к записи номера страницы кроме регистра ещё в какую-то ячейку памяти. Фигня.

В общем, не придумал способа КАК из сигналов шины (и только) реализовать управление ногой CS, поэтому вывел её на отдельную ножку МК. Отключаем доступ к памяти CS=1 для перезаписи номеров страниц и включаем CS=0 в макросе emsOn(). Теперь дополнительная нога микроконтроллера управляет сигналом CS через вход "EN", к которому она подсоединяется внешним проводом, соответственно можно выбрать любую. У меня сейчас это PCINT15 (см. пост№77)

strannic1
Offline
Зарегистрирован: 16.02.2016

а глупый вопрос - можно приобрести платы или попросить чертежы плат в спринтлауте или аналогичном для повторения....Заранее спасибо.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Можно. Пишщите на почту arhat109 собака на мейл который ru, впрочем тут мой ящик тиражирован многажды. :)

P.S. Готовых плат сейчас уже нет. Сами платы травятся, наносятся все обозначения в Китае (тут есть где). Для повтора есть только вариант в линуксо-праведном Kicad..

Для платы из поста №88 сейчас из Китая едут платы ОЗУ на 512кб + разьем для SD-карт по SPI шине. Жду, новую версию для пайки "последнего релиза".. :)

selevo
selevo аватар
Offline
Зарегистрирован: 21.12.2013

а мочему нельзя было сделать  все как  у платы ардуино 2560 r3  ?

Beginer123
Offline
Зарегистрирован: 23.11.2018

У меня сохранились эти ссылки:

http://arduino.ru/forum/otvlechennye-temy/vopros-dlya-obsuzhdeniya - тут наверное самый полный ответ на Ваш вопрос.

http://arduino.ru/forum/obshchii/atmega-128a-au-vneshnyaya-sram-62256-74... - ещё одна успешная попытка для 64кб и Атмега128а

arduino.ru/forum/proekty/lego-kirpich-iz-mega2560 - ещё одна тема Архата, есть про многое в т.ч. и меги с памятью

arduino.ru/forum/proekty/nedovolnym-super-dunya-est-zhelayushchie-prinyat-uchastie поиском (верхний правый угол) нашлась ещё эта тема..

selevo
selevo аватар
Offline
Зарегистрирован: 21.12.2013

да ну нах...    можно было просто  увеличить  с краев, добавив ряды контактов и плату оставить  формата  ардуино мега,  дичь полная получилась - никому, кроме  10ти человек,  ненужная. Вообще  дичь, с учетом того что плата  и схема  ардуины меги есть всети к тому же там еще куча  места пустого. Меня надо было српосить прежде чем делать.