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

Узнать в run-time занимаемую память приложения

Приветствую!

Среда Keil uVision, версия 5.25.2.0 (не думаю, что это важно).

Хочу сделать в своем GUI маленький такой раздел с ресурсными параметрами самого МК: сколько занимает прошивка во Flash, сколько выделено ОЗУ, а также разные финтиклюшки (процент загрузки CPU и т.д.). Возможно ли средствами линкера (или как еще?) разместить в две константные ячейки Flash количество занимаемых байт памяти во Flash (образ прошивки) и ОЗУ?

После компиляции эти параметры известны (пишутся в build output): .text, .bss и т.д., но вот как бы их еще из run-time выцыганить...

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


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

27 минут назад, Arlleex сказал:

Возможно ли средствами линкера (или как еще?) разместить в две константные ячейки Flash количество занимаемых байт памяти во Flash (образ прошивки) и ОЗУ?

После компиляции эти параметры известны (пишутся в build output): .text, .bss и т.д., но вот как бы их еще из run-time выцыганить...

Можно конечно. В чём проблема? Забыли как слово const пишется?  :wink2:

Вычисление размера памяти: расположить в конце и в начале региона памяти определённые секции и вычислить разницу между ними. Не знаю как в Keil, но в IAR файл .icf:

define block IMAGE_HEAD with fixed order {section .intvec, section .checksum,
  section .codehead, section .intvecTail, section .codebegin};
place in RAM_regionB {ro, first block IMAGE_HEAD, last section .codetail,
  section .rodataInternal, section .textInternal, section .constFast};
define block IMAGE_HEAD_EXT with fixed order {section .codeheadExt};
place in SDRAM_regionA {
  first block IMAGE_HEAD_EXT,
  section .codeSignature,
  section .fnt,
  ...
  last section .codetailExt
};

Файл .asm:

SECTION  .codeheadExt:CONST:ROOT(0)
SECTION  .codetailExt:CONST:ROOT(0)

Файл .cpp:

__noreturn int main()
{
  #pragma section=".intvec"
  #pragma section=".codetail"
  #ifdef _CODE_SDRAM
  #pragma section=".codeheadExt"
  #pragma section=".codetailExt"
  #endif //_CODE_SDRAM
  ...
  LogCR0("Program image size: %u bytes",
    #ifdef _CODE_SDRAM
    (u32)__section_end(".codetailExt") - (u32)__section_begin(".codeheadExt") +
    #endif //_CODE_SDRAM
    (u32)__section_end(".codetail") - (u32)__section_begin(".intvec"));
  ...
}

Это пример для более сложного случая - когда программа разделена на 2 несмежных региона памяти. Если всё одним куском - будет ещё проще.

В моём случае - отладочная сборка для выполнения в SDRAM состоит из двух регионов (как видно выше) и _CODE_SDRAM - defined. При сборке во флешь _CODE_SDRAM будет - undef.

 

PS: Секции ".codeheadExt" и ".codetailExt" - пустые. 0-го размера. Как создать пустые секции в .cpp я не знаю, поэтому они в .asm.

PPS: У IAR-а (7.80.4) есть какой-то глюк с расположением секций в начале региона (first section ...) - почему-то это не всегда срабатывает. А вот "first block" - срабатывает всегда. Поэтому в моём примере пришлось сделать отдельный блок IMAGE_HEAD_EXT только с одной секцией.

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


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

18 минут назад, jcxz сказал:

Можно конечно.

То что нужно, похоже. Попутно накопал еще топик для размышления.

Спасибо!

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


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

Не скажу за все среды, но если сборка идёт с использованием командной строки LD, то можно использовать для него "скрипты" - там можно выводить в глобальные переменные константы-адреса секций и результаты операций над ними, можно добавлять новые секции и модифицировать существующие. Можно даже в два прохода компоновку делать - на первом допустим размер пользовательской секции задан нулевой, а на втором - как результат разбора файла от первого этапа с учётом получившихся размеров/адресов.

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


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

10 hours ago, Arlleex said:

. . . После компиляции эти параметры известны (пишутся в build output): .text, .bss и т.д., но вот как бы их еще из run-time выцыганить...

Посмотрите список макро-переменных препроцессора, возможно там есть "сегментные" 

Predefined macros

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


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

6 hours ago, Arlleex said:

Благодарю всех за комментарии. Выбор мой пал, все-таки, на средства линкер-скрипта.

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

Я предпочитаю сканировать память и выводить инфу о чистых кусках по факту:

    // Проверяем заполнение памяти
    uint8_t  *str_addr = (uint8_t *)0x00000000;
    uint8_t  *addr;
    uint8_t  *end_addr = (uint8_t *)0x003FFFFF;
    uint8_t  *end = 0;
    uint32_t  empt_bl_sz = 0;

    addr = str_addr;
    do
    {
      if (*addr != 0xFF)
      {
        if (empt_bl_sz > 256)
        {
          MPRINTF("Empty flash memory from %08X to %08X\r\n", (uint32_t)end - empt_bl_sz , (uint32_t)end);
        }
        empt_bl_sz = 0;
      }
      else
      {
        end = addr;
        empt_bl_sz++;
      }
      addr++;

    } while (addr <= end_addr);

    if (empt_bl_sz > 256)
    {
      MPRINTF("Empty flash memory from %08X to %08X\r\n", (uint32_t)end - empt_bl_sz , (uint32_t)end);
      MPRINTF("Occupied flash memory size  %d\r\n", (uint32_t)end - empt_bl_sz - (uint32_t)str_addr);
    }
    else
    {
      MPRINTF("Occupied flash memory size  %d\r\n", (uint32_t)end_addr - (uint32_t)str_addr);
    }

Таким образом не пропустите опасный мусор и другие чудесные артефакты. 

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


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

18 часов назад, AlexandrY сказал:

Я предпочитаю сканировать память и выводить инфу о чистых кусках по факту...

Я думал о таком варианте, но в ней есть свои минусы:

1. Я не всегда стираю полностью все сектора при программировании. Я стираю только те, что нужны под приложение. Да, бывает и стираю полностью (но гарантии нет, что это у меня дэ-факто).

2. Время выполнения этой функции сильно зависит от объема занятой памяти.

3. С ОЗУ такой вариант уже не прокатит...

 

Плюс, конечно, в том, что не надо заморачиваться и вспоминать, что там загрузчик еще где-то может существовать и т.д. Но, ИМХО, программист должен это учитывать при написании целевого приложения и уменьшать реальный объем доступной памяти. Например, если в устройстве предусмотрен загрузчик (и пусть занимает он 16кб), то для МК с объемом Flash 2 Мб достаточно сказать линкеру, что реальной памяти, отведенной приложению, осталось 2Мб - 16кб.

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


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

2 hours ago, Arlleex said:

1. Я не всегда стираю полностью все сектора при программировании. Я стираю только те, что нужны под приложение. Да, бывает и стираю полностью (но гарантии нет, что это у меня дэ-факто).

Нестертые сектора и есть довольно опасный  мусор. Эт вы наверно, как и я поняли когда запустили этот код. :biggrin:
Время на 4 Мбайтах занимает меньше секунды. Так что переживать не о чем. 
 

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


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

Если говорить о компиляторе ARMCC, то можно прочитать на сайте

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0474c/CHDDGJGB.html

В других компиляторах тоже всё есть.

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


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

Линкер создаёт всякие символы с информацией об адресах и размерах. К ним можно обращаться из сишного исходника.

http://www.keil.com/support/man/docs/armlink/armlink_pge1362065951495.htm

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


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

15 часов назад, AlexandrY сказал:

Время на 4 Мбайтах занимает меньше секунды. Так что переживать не о чем. 

А если секунда - это недопустимо большое время для старта ПО данного устройства? не думали?

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


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

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

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

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

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

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

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

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

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

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