Comments 27
Stream.print(const __FlashStringHelper*)
typedef struct {
unsigned char array2d[2][3];
} x_t;
...
const x_t v PROGMEM = {...};
...
unsigned char a = pgm_read_byte_far(pgm_get_far_address(v) + offsetof(x_t, array2d[i][j]));
Надо переходить на ARM, где единное 32 битное адресное пространство (если не перешли).
0 по 0x007fffff
подскажите о каком контролере идет речь? где такие большие адреса присутствуют?
Понятия не имею, у какого микроконтроллера есть 8 МБ флеша. В серии ATmega, насколько я знаю, максимум 256 КБ; ATxmega — 392 КБ. В статье речь не о размере флеша микроконтроллера, а об адресном пространстве, выбранном разработчиками адаптированного для архитектуры AVR компилятора GCC. С практической точки зрения важно, что существую микроконтроллеры с более, чем 32 КБ флеша, а не существуют ли с 8 МБ.
вы уж извините, но что то я не могу понять кто тупит. у авр ведь разделенное адресное пространство. а то что вы пишете что-то не соответствует реальности:
"под код (ПЗУ, flash) отводятся адреса с 0 по 0x007fffff, а под данные (ОЗУ, SRAM) — с 0x00800100 по 0x0080ffff. "
я в отладке смотрю адресацию на атмега2560 и вижу там следующее.
data registers имеет адреса 0x0000 - 0x21FF
prog flash имеет адреса 0x000000 - 0x7FFF
я потратил вечер на то чтоб понять что к чему..
и у меня в атмел студио без проблем работает следующая конструкция:
pgm_read_dword_far( pgm_get_far_address(hz))
перечитав коммент понял что ошибся: prog flash имеет адреса 0x000000 - 0x3FFFF
и еще вы не упомянули такой фактор как переход к нулевому адресу без инкрементирования смещения. допустим если было 0x1FFFF и мы добавили один то станет 0x10000. не знаю еще как это прогнать в железе чтоб проверить. но в коментариях на многих англоязычных сайтах пишут что так и есть
вообщем у меня полное разочарование. я хотел создать два массива, один в оперативке, а второй в памяти програм но на границе 0x1FFFF, чтоб посмотреть что будет переписываться во второй массив во время перехода. и что я вижу. конструкция типа:
for (int x = 0; x < 399; x ++){ for (int y = 0; y < 19; y ++){ perehodreal[x][y] = pgm_read_dword_near(&(array2d[x][y])); } }
работает без проблем. а вот если мы используем дальний адрес то вываливается ошибка и ничего не компилируется.
for (int x = 0; x < 399; x ++){ for (int y = 0; y < 19; y ++){ perehodreal[x][y] = pgm_read_dword_far(pgm_get_far_address(perehod[x][y])); } }
единственный вариант что я вижу это втупую прибавлять к адрессу 4 и считывать это значение в свой массив. но как мне кажется это максимально тупо
так что скажите? есть у вас идеи по этому поводу?
Я не уверен, что понял вашу проблему, и у меня нет желания тратить время на это. Если вы пришлёте мне свой проект, может быть, я разберусь. Пока что я могу лишь предположить, что вы невнимательно читали статью. Я же написал, что pgm_get_far_address не умеет работать с элементом массива, вычисляемым во время работы; ей нужно подать определённый при компиляции указатель (другими словами, сам массив), а смещение делать вручную (через арифметику указателей. Вам знаком этот термин?). При этом я не понимаю, почему у вас работает pgm_read_dword_near; вы уверены, что данные расположены после 64 КБ?
О проблеме 0x1FFFF + 1 = 0x10000 слышу впервые; похоже, кто-то (кто? Компилятор GCC? Какая-то конструкция библиотеки AVR-libc? Отладчик Студии?) производит сложение по модулю 0x10000 (64 К) в младших 16 битах, но при этом сохраняет старшие (или всегда производит смещение на 0x10000). Также стоит помнить о том, что в микроконтроллерах AVR одни и те же вещи (например, адреса флеша) в одних местах исчисляются в байтах, а в других — в словах. Ещё я не понял, почему ваша проблема может быть решена прибавлением 4. Почему именно 4, откуда такая константа?
Преодоление порога 32 КБ для данных в ПЗУ микроконтроллеров AVR