1

Тема: Виділення визначеної адреси пам'яті в AVR

Добридень, панове!
Є МК Atmega8 (хоча, я гадаю, це не зовсім важливо). Пишу загалом на C з асемблерними вставками.
Хочу в області пам'яті FLASH зробити однобайтовий масив, який починається за фіксованою адресою вказаною мною. І як можна якось компілятору C "пояснити", щоб цю область FLASH не чіпав? Бо на asm писати все, для мене буде важко :) Хоч там я собі і можу пояснити, що то не треба чіпати :D

Мені потрібна саме така визначена область, для швидкодії в асемблерній вставці. Масив розміром 256 байт (256 значень) і тому зручно звертатися до нього, завантаживши до XH, YH або ZH фіксований старший байт адреси, а до XL, YL або ZL індекс, оскільки читання масиву не послідовне, а хаотичне. А мені ті два чи три такти, важливі.

До речі цікавить така можливість і для SRAM, але то вже не важливо.

Дякую за увагу.

Зробити можна все, головне мати терпіння й бажання

2

Re: Виділення визначеної адреси пам'яті в AVR

Для avr-gcc це можна зробити через визначення спеціальної секції в пам'яті і редагування лінкерного скрипта (тоді найгнучкіше керування), а можна через __attribute__(( aligned( N ) )).

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

#include <avr/pgmspace.h>

// тут може бути лише степінь двійки
const unsigned char array[256] __attribute__((aligned(256))) PROGMEM = {1,2,3};

avr-gcc -mmcu=atmega8 -S

        .file   "a.c"
.global array
        .section        .progmem.data,"a",@progbits
        .p2align        8     //  оця команда каже лінкеру, що треба вирівнятися на 2^8 байтів, пропустивши місце
        .type   array, @object
        .size   array, 256
array:
        .byte   1
        .byte   2
        .byte   3
        .zero   253
        .ident  "GCC: (GNU) 4.9.2"

А першим варіантом можна запхати під вершечок флеша та й усе. Але то лише завтра ввечері намалюю.

printf("Nested comments is %s\n", */*/**/"*/"/*"/**/ == '*' ? "OFF" : "ON");
Подякували: Volodya96, LoganRoss, leofun013

3

Re: Виділення визначеної адреси пам'яті в AVR

Volodya96 написав:

… зручно звертатися до нього, завантаживши до XH, YH або ZH фіксований старший байт адреси, а до XL, YL або ZL індекс, оскільки читання масиву не послідовне, а хаотичне.

До речі цікавить така можливість і для SRAM, але то вже не важливо.

Ну якщо флеш, то тоді лише ZH.
Для SRAM все точно так само.

printf("Nested comments is %s\n", */*/**/"*/"/*"/**/ == '*' ? "OFF" : "ON");
Подякували: Volodya961

4 Востаннє редагувалося Volodya96 (26.06.2018 10:37:01)

Re: Виділення визначеної адреси пам'яті в AVR

ReAl написав:

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

#include <avr/pgmspace.h>

// тут може бути лише степінь двійки
const unsigned char array[256] __attribute__((aligned(256))) PROGMEM = {1,2,3};

Дякую за настільки детальні та зрозумілі пояснення. Не знав про цей атрибут. Мені підходить другий спосіб: розміщення там, де вийде. Хоча про перший, також хотілося б дізнатися. Старший байт адреси передам аргументом до асемблерної вставки, оскільки на етапі ініціалізації швидкість не критична.

P.S. Піду й скористаюся Вашою порадою, сподіваюся cпрацює :)

Зробити можна все, головне мати терпіння й бажання

5 Востаннє редагувалося ReAl (28.06.2018 09:13:41)

Re: Виділення визначеної адреси пам'яті в AVR

Трохи одна справа часу забирає, ніколи докладно розписати з архівом потрібних файлів (щоб точно працювало).
Поки на тему секцій/лінкера можна подивитися:
Секції .init в avr-gcc (зручно дещо робити, невелика економія коду)
Використання секцій в GCC (теж на прикладі avr-gcc, хоча якщо очистити від PROGMEM і секцій .init, то воно універсальне, схожі технології використовуються в ядрі лінукса)

Перше не використовує ніяких доповнень до лінкерного скрипта, використовуються штатні можливості пакету для AVR. Друге навіть складніше, ніж то потрбно для розміщення масиву в окремій секції, але воно не фіксує і не вирівнює адресу початку, тому теж не підійде і я таки зроблю спеціальний приклад. Але для ознайомлення з темою секцій та керування ними і лінкерному скрипті буде корисним.

printf("Nested comments is %s\n", */*/**/"*/"/*"/**/ == '*' ? "OFF" : "ON");
Подякували: leofun011