Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Массив по заданному адресу MDK-ARM (Keil)
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
quandr
Добрый день.
В документации MDK-ARM описана возможность размещения переменной по заданному адресу.
Например
int x2 __attribute__((at(0x12000))) = 10;

А как массив разместить в определенном адресном пространстве (может как-то через первый элемент)?

Спасибо!
__inline__
Три способа:

1) Сделать в линкере секцию и через #pragma section объявлять массив

2) Так же как вы написали : char Buffer[1024] __attribute__((at(0x38800000)));

3) char *Buffer=(char*)0x38000000; Обращаться Buffer[i]=j;
k155la3
В файле линкера организовать сегмент и при декларации массива указать его использование в attr.
Как в MDK не знаю, возможно имя сегмента указать вместо at(0x12000).
Это обеспечит гарантию, что компилятор будет "знать" что этот адрес занят, и не будет накладок.
В приведенном Вами коде это не гарантируется.
Arlleex
Цитата(__inline__ @ Jul 7 2018, 16:46) *
3) char *Buffer=(char*)0x38000000; Обращаться Buffer[i]=j;

Никому больше такое не говорите biggrin.gif
aaarrr
Цитата(Arlleex @ Jul 7 2018, 18:45) *
Никому больше такое не говорите biggrin.gif

Ну, вся работа с регистрами периферии так строится - ничего же wink.gif Другое дело, что при таком подходе следует спрятать от линкера тот диапазон адресов, где происходит ручное распределение. А если так, то проще уж сразу определить отдельную секцию.
Arlleex
Цитата(aaarrr @ Jul 7 2018, 19:01) *
Ну, вся работа с регистрами периферии так строится - ничего же wink.gif Другое дело, что при таком подходе следует спрятать от линкера тот диапазон адресов, где происходит ручное распределение. А если так, то проще уж сразу определить отдельную секцию.

Регистры это заранее определенные области, а компилятор размещает переменные где захочет в соответствии с линкерскриптом. Указали возможность 3 способами, первый из которых как раз указание линкеру. Тогда это сработает, да. Но способ писать по адресу подразумевался как отдельный способ без шаманства с линкерскриптом rolleyes.gif В таком случае можно затереть какие-нибудь переменные.
pnp_mechanic
Можно так.
const uint16_t NAME [] __attribute__((at(0x08002000))) = {...}
haker_fox
QUOTE (k155la3 @ Jul 7 2018, 23:41) *
В файле линкера организовать сегмент и при декларации массива указать его использование в attr.

Я тоже за такой подход. Т.е. конкретными адресами пусть занимается файл линкера. Всегда так делаем. Правда используем IAR, но это сути вообще не менят.
quandr
Цитата(__inline__ @ Jul 7 2018, 16:46) *
Три способа:

1) Сделать в линкере секцию и через #pragma section объявлять массив

2) Так же как вы написали : char Buffer[1024] __attribute__((at(0x38800000)));

3) char *Buffer=(char*)0x38000000; Обращаться Buffer[i]=j;


Куда вписывать #pragma section и как объявлять массив в данном случае? Извините, не делал такого раньше. Поэтому, если можете, чуть подробнее.
KRS
Цитата(aaarrr @ Jul 7 2018, 19:01) *
Ну, вся работа с регистрами периферии так строится - ничего же wink.gif

Вообще то не так sm.gif

char *Buffer=(char*)0x38000000;

снижает скорость и увеличивает расход памяти! потому что лишняя переменная вводится...

надо так
#define Buffer ((char*)0x38000000)
__inline__
Объявил переменную в секции SRAM3:
Код
u8 AudioBuffer[1024] __attribute__((section("SRAM3")));


Скаттер-файл:
Код
LR_IROM1 0x08000000 0x00200000  {   ; load region size_region

  ER_IROM1 0x08000000 0x00200000  { ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }

  DTCM 0x20000000 0x00020000  { ; RW data
  }

  AXI 0x24000000 0x00080000  { ; RW data
   .ANY (+RW +ZI)
  }

  SRAM12 0x30000000 0x00040000  { ; RW data
   .ANY (+RW +ZI)
  }

  SRAM3 0x30040000 0x00000008  { ; RW data
   .ANY (+RW +ZI)
  }

  SRAM4 0x38000000 0x00010000  { ; RW data
  }

}


Из скаттера видно, что секция SRAM3 всего 8 байт, а надо 1024.

Тем не менее, линковка успешна!

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

Что я сделал не так?

выдержка из МАР-файла. точно, вообще в другую секцию засунул!

как победить урода? (Keil)

или только через :
1) u8 *AudioBuffer=(u8*)0x30040000;
2) u8 AudioBuffer[1024] __attribute__((at(0x30040000)));

?
Нажмите для просмотра прикрепленного файла
quandr
Цитата(aaarrr @ Jul 7 2018, 19:01) *
Ну, вся работа с регистрами периферии так строится - ничего же wink.gif Другое дело, что при таком подходе следует спрятать от линкера тот диапазон адресов, где происходит ручное распределение. А если так, то проще уж сразу определить отдельную секцию.

Так как всё таки записать эту секцию для массива в IRAM2 например int Arr [1024]? С началом по конкретному адресу.
Forger
Цитата(quandr @ Jul 8 2018, 16:04) *
Так как всё таки записать эту секцию для массива в IRAM2 например int Arr [1024]? С началом по конкретному адресу.

Ведь все есть в мануале на Keil. Вот первые же ссылки, который дал гугль:
http://www.keil.com/support/man/docs/armli...62066000009.htm
http://www.keil.com/support/man/docs/armcc...59124982450.htm
quandr
Цитата(Forger @ Jul 8 2018, 17:08) *
Ведь все есть в мануале на Keil. Вот первые же ссылки, который дал гугль:
http://www.keil.com/support/man/docs/armli...62066000009.htm
http://www.keil.com/support/man/docs/armcc...59124982450.htm

Там только регион указан, а мне по адресу нужно.
Forger
Цитата(quandr @ Jul 8 2018, 18:42) *
Там только регион указан, а мне по адресу нужно.

Эх, совсем молодежь обленела .... angry.gif
http://www.keil.com/support/man/docs/armli...62066000571.htm

Имхо, вместо размещения объектов по конкретному адресу, лучше использовать размещение в секциях, а размещение самих секций делать в соотв. scatter файле (скрипт линкера).
quandr
Цитата(Forger @ Jul 8 2018, 19:08) *
Эх, совсем молодежь обленела .... angry.gif
http://www.keil.com/support/man/docs/armli...62066000571.htm

Имхо, вместо размещения объектов по конкретному адресу, лучше использовать размещение в секциях, а размещение самих секций делать в соотв. scatter файле (скрипт линкера).

Если бы молодость, было бы веселее. А так полтинник, и башка занята чем попало... Кейл только вкусов в коктейль добавил ))
Forger
Цитата(quandr @ Jul 8 2018, 19:40) *
Если бы молодость, было бы веселее. А так полтинник, и башка занята чем попало...

Сочувствую 05.gif
Все когда-то начнем тупить на абсолютно ровном месте ...

__inline__
Цитата(Forger @ Jul 8 2018, 17:08) *
Эх, совсем молодежь обленела .... angry.gif
http://www.keil.com/support/man/docs/armli...62066000571.htm

Имхо, вместо размещения объектов по конкретному адресу, лучше использовать размещение в секциях, а размещение самих секций делать в соотв. scatter файле (скрипт линкера).


Выше я дал пример (который почему-то все проигнорировали), что размещение в секции - ещё не гарантирует фактического туда попадания.
Поэтому размещение по конкретному адресу - способ надёжнее
Forger
Цитата(__inline__ @ Jul 9 2018, 06:26) *
Выше я дал пример (который почему-то все проигнорировали), что размещение в секции - ещё не гарантирует фактического туда попадания.


В вашем примере не объявлена секция SRAM3, а объявлен регион с таким названием.
Короче, вот тут почитайте: http://www.keil.com/support/man/docs/armcl...62066000009.htm

Для примера вот так в Keil я делал RAM функции ("стандартный" метод меня не устраивает):

scatter:
Код
RW_IRAM1 0x20000000 0x00004000; RW data
{  
    *.o (RAM_FUNCTION)    
    .ANY (+RW +ZI)
}


в исходниках:

Код
#define RAM_FUNCTION __attribute__ ((section("RAM_FUNCTION")))

static RAM_FUNCTION Status getStatus() ...
RAM_FUNCTION Status waitForLastOperation(uint32_t timeout) ...
RAM_FUNCTION void stm32l1::Flash::enableRunPowerDown() ....
aaarrr
Цитата(__inline__ @ Jul 8 2018, 15:50) *
Что я сделал не так?

В приведенном скаттер-файле нет секции SRAM3.
HardEgor
Цитата(__inline__ @ Jul 9 2018, 10:26) *
Выше я дал пример (который почему-то все проигнорировали), что размещение в секции - ещё не гарантирует фактического туда попадания.

Пример неудачный - естественно массив в 1024 байте никто не сможет разместить в секцию размером 8 байт.
Но в общем случае да, если свободной памяти под ноль, то при оптимизации может в другую секцию засунуть.
Forger
Цитата(HardEgor @ Jul 9 2018, 09:31) *
Пример неудачный - естественно массив в 1024 байте никто не сможет разместить в секцию размером 8 байт.
Но в общем случае да, если свободной памяти под ноль, то при оптимизации может в другую секцию засунуть.

Не засунет, линкер просто выкинет соотв. ошибку, бинарник не будет создан.
__inline__
ок, попробую разобраться
__inline__
Цитата(Forger @ Jul 9 2018, 07:34) *
Не засунет, линкер просто выкинет соотв. ошибку, бинарник не будет создан.

Разобрался. Ошибка была в том, что сделал регионы, но секции не засунул. Потому что считал что регион=секция. Оказалось сложнее.
Получилось вот так:
Код
; Scatter-Loading Description File

LR_FLASH 0x08000000 0x00200000
{

ER_FLASH 0x08000000 0x00200000
{
  *.o (RESET, +First)
  *(InRoot$$Sections)
  .ANY (+RO)
}

DTCM 0x20000000 0x00020000
{
  *.o (DTCM)
}

AXI 0x24000000 0x00080000
{
  .ANY (+RW +ZI)
}

SRAM12 0x30000000 0x00040000
{
  *.o (SRAM12)
}

SRAM3 0x30040000 0x00008000
{
  *.o (SRAM3)
}

; SRAM4 0x38000000 0x00010000
; {
;  *.o (SRAM4)
; }

}


Я доволен : всё пихается куда надо и работает sm.gif
Forger
Цитата(__inline__ @ Jul 9 2018, 16:22) *
Разобрался.

Дык, это и не удивительно, когда комрады тут все разжевали до косточек и осталось лишь проглотить sm.gif

Scatter файл позволяет делать очень интересные вещи ... , а это - лишь цветочки wink.gif

Вместо такой записи, где две области примыкают друг к другу:
Код
SRAM12 0x30000000 0x00040000
{
  *.o (SRAM12)
}

SRAM3 0x30040000 0x00008000
{
  *.o (SRAM3)
}


можно писать чуть проще:

Код
SRAM123 0x30000000 0x000С0000
{
  *.o (SRAM12)
  *.o (SRAM3)
}
__inline__
Цитата(Forger @ Jul 9 2018, 14:26) *
Дык, это и не удивительно, когда комрады тут все разжевали до косточек и осталось лишь проглотить sm.gif

Scatter файл позволяет делать и не такое, а это - лишь цветочки wink.gif

Вам спасибо персонально! sm.gif С ваших слов понял, что секция и регион -не одно и тоже
Forger
Цитата(__inline__ @ Jul 9 2018, 16:28) *
Вам спасибо персонально! sm.gif С ваших слов понял, что секция и регион -не одно и тоже

Пожалуйста ))

Но в принципе, все это есть в мануале, довольно популярно расписано.
__inline__
Продолжая о скаттерах...

Понадобилось мне сделать буфер в RAM, который не трётся при сбросе CPU (для сохранения состояния).

Объявил регион, секцию - обязательно указываем UNINIT:

Код
AXI3 0x2405B500 UNINIT 0x00024B00;STATE
{
  *.o (STATE)
}


В программе - обязательно указываем zero_init:

Код
u8 STATE[0x00024B00] __attribute__((section("STATE"),zero_init));


Кейла тут говорит, что zero_init обязателен - типа косяк: SYMPTOM/ CAUSE/ RESOLUTION/ => http://www.keil.com/support/docs/3480.htm

Проверил, действительно без указания zero_init память трётся при сбросе CPU.
Forger
Цитата(__inline__ @ Jul 16 2018, 08:26) *
Продолжая о скаттерах...

Полезная инфа!
Судя по приписке, это справедливо только для маленьких объектов размером до 8 байт.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.