Страница 1 из 8
Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 11:05:04
afz
Тут идут исторические размышления на тему... Спойлер
Когда появился язык Си, распределение памяти для него сделали стандартным для PDP-11, где он впервые появился. А именно, с начала памяти, сразу после области векторов, располагался стек, за ним программа, а после программы - куча, и все остальное. Расположить стек в конце памяти было нельзя - там была операционка, которая, к тому же могла подгружать свои части туда же, т.е. верхний свободный адрес был нестационарным. Для программирования на Си это было весьма неудобно - приходилось разбираться, какого размера нужен стек каждой из программ и указывать нужные ключи линкеру.
Потом пришли времена MS-DOS и эта проблема ушла: в начале памяти операционка, за ней сама программа, далее вся память свободна, с ее начала располагают кучу, в конце - стек, и вперед, пока стек с кучей не столкнутся. (Я уж не говорю про винды, в которых для обозримых задач память можно считать бесконечной).
Да и на МК - на тех же AVR - стек кладут в конец ОП, кучу - в начало. А вот на хрена для АРМов сделали такую глупость, как стек в начале памяти? Чтобы добавить юзерам геморрою? Посчитай, мол, еще и стек... Я правильно понимаю, что локальные для функции переменные и массивы располагаются в области стека? А статические и глобальные (в смысле, определенные вне функций и видимые во всех функциях) - перед кучей, да? Ну, и malloc() выдаст память из кучи, да?
Re: Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 11:13:07
Мурик
afz писал(а):Я правильно понимаю, что локальные для функции переменные и массивы располагаются в области стека?
Как правило да.
afz писал(а):А статические и глобальные (в смысле, определенные вне функций и видимые во всех функциях) - перед кучей
Необязательно. Распределением что и где (если явно не заданно) занимается компилятор/линкер.
afz писал(а):А вот на хрена для АРМов сделали такую глупость, как стек в начале памяти?
Вначале таблицы векторов находится указатель на стек, а он обычно располагается в конце памяти.
Re: Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 13:16:55
Z_h_e
Из файла
startup_stm32f10x_md.c
Код: Выделить всё
#define STACK_SIZE 0x00000100 /*!< The Stack size suggest using even number */
__attribute__ ((section(".co_stack")))
unsigned long pulStack[STACK_SIZE];
Т.е. в секции .co_stack размещен массив размером STACK_SIZE - это и есть зарезервированная области для стека. Линковщик секцию .co_stack расположит последней среди всех секций ОЗУ.
В таблице векторов такая запись
Код: Выделить всё
(void *)&pulStack[STACK_SIZE], /*!< The initial stack pointer */
Reset_Handler, /*!< Reset Handler */
NMI_Handler,
...
...
Т.е. указатель стека инициализируется адресом расположения последнего элемента массива pulStack. Если хочется однозначно указать на конец памяти, то можно строку (void *)&pulStack[STACK_SIZE], заменить например на (void*)(0x2000xxxx) . Ну или вставку ассемблерную вставить изменяющую указатель стека. Однако лучше изменять только STACK_SIZE, тогда ты точно знаешь сколько у тебя выделено памяти на стек.
Это для компилятора GCC, у других как там я не знаю.
Re: Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 14:29:43
VladislavS
[uquote="Z_h_e",url="/forum/viewtopic.php?p=3442225#p3442225"]Это для компилятора GCC, у других как там я не знаю.[/uquote]Да в принципе у всех примерно одинаково. Хочу лишь уточнить, что скриптом линкера стэк можно хоть на кукушку, хоть за можай загнать.
Re: Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 19:48:58
afz
Z_h_e писал(а):Это для компилятора GCC, у других как там я не знаю.
У Кейла то же самое, не считая того, что стартап у него на асме.То есть, все обследованные системы программирования в начале SRAM располагают статические переменные, затем кучу заданного размера и стек, тоже заданного размера. Да, я уточнил, Кейл по malloc() выдает память из кучи, думаю, остальные делают то же самое.
Получается, что остальная оперативка просто недоступна. Спрашивается, зачем? Ведь линкер собирает программу для конкретного камня, размер его памяти заведомо известен. Кто мешал стек разместить в физическом конце оперативки и не фиксировать соотношений между стеком и кучей - пусть растут навстречу друг другу, пока не встретятся. Так нет, нас заставляют рулить еще двумя параметрами, причем их дефолтные размеры поставлены просто смешными. На чем часто обламываются начинающие.
В общем, непонятно, зачем так сделали...
Re: Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 20:00:41
Z_h_e
afz писал(а):В общем, непонятно, зачем так сделали...
Я думаю в скрипте линковщика можно жестко указать, где должен находится сегмент стэка. И тогда можно будет более корректно установить указатель стека в конец памяти.
Добавлено after 4 minutes 4 seconds:
afz писал(а):Получается, что остальная оперативка просто недоступна.
ЯВУ как бы избавляет программера думать об распределении памяти. Добавил переменныю - все "само" сдвинулось. Добавил много - наругается. Так что вся доступна, только надо заявить сколько тебе надо.
Re: Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 20:06:23
Мурик
afz писал(а):Кто мешал стек разместить в физическом конце оперативки и не фиксировать соотношений между стеком и кучей - пусть растут навстречу друг другу, пока не встретятся.
Стек может быть в конце оперативки.
Спойлер
Адрес 0x20005000 это конец оперативки у STM32F103C8T6. Компилятор GCC. Скрипт линкера стандартный из IDE.
Re: Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 20:12:44
VladislavS
[uquote="afz",url="/forum/viewtopic.php?p=3442464#p3442464"]Получается, что остальная оперативка просто недоступна. Спрашивается, зачем? Ведь линкер собирает программу для конкретного камня, размер его памяти заведомо известен.[/uquote]Линкер выделяет программе ровно столько памяти сколько ей нужно. Зачем давать программе больше чем ей нужно? Она от этого лучше работать не будет.
[uquote="afz",url="/forum/viewtopic.php?p=3442464#p3442464"]Кто мешал стек разместить в физическом конце оперативки и не фиксировать соотношений между стеком и кучей - пусть растут навстречу друг другу, пока не встретятся.[/uquote]Кто запрещает вам это сделать? Скрипт линкера и стартап доступны для редактирования - пишите как считаете нужным. От себя лишь пожелаю, чтобы они всё же не встречались у вас.
[uquote="afz",url="/forum/viewtopic.php?p=3442464#p3442464"]Так нет, нас заставляют рулить еще двумя параметрами, причем их дефолтные размеры поставлены просто смешными.[/uquote]Нормальные размеры, просто использовать их надо с головой.
Re: Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 20:30:24
Z_h_e
Мурик писал(а):Адрес 0x20005000 это конец оперативки у STM32F103C8T6. Компилятор GCC. Скрипт линкера стандартный из IDE.
А вот у меня пример небольшой прожки со стандартным линкером на тот же камень.
Спойлер

Добавлено after 7 minutes 4 seconds:
Мурик писал(а):Адрес 0x20005000 это конец оперативки у STM32F103C8T6.
Хммм. Размер то ОЗУ до 0x20004FFF. Разве не должен быть максимальный адрес для 32битного регистра быть 0x20004FFC для такого размера памяти?
Добавлено after 4 minutes 50 seconds:
Хотя, видимо укзатель сначала уменьшается и потом запись, а увеличивается уже после чтения.
Re: Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 20:56:46
afz
А у Кейла все оказалось гоораздо хуже! Автоматические (локальные) переменные Кейл располагает после стека.
Z_h_e писал(а):ЯВУ как бы избавляет программера думать об распределении памяти. Добавил переменныю - все "само" сдвинулось. Добавил много - наругается. Так что вся доступна, только надо заявить сколько тебе надо.
VladislavS писал(а):Линкер выделяет программе ровно столько памяти сколько ей нужно. Зачем давать программе больше чем ей нужно? Она от этого лучше работать не будет.
Не всегда. Я часто пользовал выделение буферов и пр. динамических областей по malloc(), разбирался, сколько там можно взять памяти и действовал должным образом, в зависимости от количества памяти.
VladislavS писал(а):Кто запрещает вам это сделать? Скрипт линкера и стартап доступны для редактирования - пишите как считаете нужным. От себя лишь пожелаю, чтобы они всё же не встречались у вас.
С Кейлом - не выйдет.
Добавлено after 5 minutes 12 seconds:
Z_h_e писал(а):Хотя, видимо укзатель сначала уменьшается и потом запись, а увеличивается уже после чтения.
Единственная архитектура, у которой в стек пишется по *SP-- - это AVR. У всех прочих запись в стек идет по *--SP, т.е., если стек пуст, его указатель должен указывать
ЗА последний байт области стека.
Добавлено after 9 minutes 27 seconds:
Мурик писал(а):afz писал(а):Я правильно понимаю, что локальные для функции переменные и массивы располагаются в области стека?
Как правило да.
Увы, у Кейла это не так!
Re: Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 21:02:23
VladislavS
[uquote="afz",url="/forum/viewtopic.php?p=3442491#p3442491"]Автоматические (локальные) переменные Кейл располагает после стека.[/uquote]Вы что-то конкретно путаете! Линкер размещает в памяти глобальные и статические локальные данные. Всё локальное в стеке и регистрах. А динамическое в куче. Это табу.
Re: Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 21:16:21
Мурик
[uquote="Z_h_e",url="/forum/viewtopic.php?p=3442480#p3442480"]
Мурик писал(а):Адрес 0x20005000 это конец оперативки у STM32F103C8T6. Компилятор GCC. Скрипт линкера стандартный из IDE.
А вот у меня пример небольшой прожки со стандартным линкером на тот же камень.
Спойлер

[/uquote]Зависит от IDE. В EmBitz вначале располагаются переменные, после куча и в конце ОЗУ находится стек. Из map файла.
Спойлер
Код: Выделить всё
.data 0x20000000 0x68 load address 0x08000570
0x20000000 __data_start__ = .
*(vtable)
*(.data*)
.data.impure_data
0x20000000 0x60 ./embitz/1.11/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/lib/armv7-m\libg_n.a(lib_a-impure.o)
0x20000060 . = ALIGN (0x4)
0x20000060 PROVIDE (__preinit_array_start, .)
*(.preinit_array)
0x20000060 PROVIDE (__preinit_array_end, .)
0x20000060 . = ALIGN (0x4)
0x20000060 PROVIDE (__init_array_start, .)
*(SORT(.init_array.*))
*(.init_array)
.init_array 0x20000060 0x4 ./embitz/1.11/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/5.4.1/armv7-m/crtbegin.o
0x20000064 PROVIDE (__init_array_end, .)
0x20000064 . = ALIGN (0x4)
[!provide] PROVIDE (__fini_array_start, .)
*(SORT(.fini_array.*))
*(.fini_array)
.fini_array 0x20000064 0x4 ./embitz/1.11/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/5.4.1/armv7-m/crtbegin.o
[!provide] PROVIDE (__fini_array_end, .)
0x20000068 . = ALIGN (0x4)
0x20000068 __data_end__ = .
.jcr 0x20000068 0x0 load address 0x080005d8
.jcr 0x20000068 0x0 ./embitz/1.11/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/5.4.1/armv7-m/crtbegin.o
.igot.plt 0x20000068 0x0 load address 0x080005d8
.igot.plt 0x20000068 0x0 ./embitz/1.11/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/5.4.1/armv7-m/crtbegin.o
.bss 0x20000068 0x1c load address 0x080005d8
0x20000068 __bss_start__ = .
*(.bss*)
.bss 0x20000068 0x1c ./embitz/1.11/share/em_armgcc/bin/../lib/gcc/arm-none-eabi/5.4.1/armv7-m/crtbegin.o
*(COMMON)
0x20000084 __bss_end__ = .
.heap 0x20000088 0x0
0x20000088 __end__ = .
0x20000088 end = __end__
*(.heap*)
.heap 0x20000088 0x0 obj\release\src\startup_stm32f10x_md.o
0x20000088 __HeapLimit = .
.stack_dummy 0x20000088 0x100
*(.stack)
.stack 0x20000088 0x100 obj\release\src\startup_stm32f10x_md.o
0x20005000 __StackTop = (ORIGIN (RAM) + LENGTH (RAM))
0x20004f00 __StackLimit = (__StackTop - SIZEOF (.stack_dummy))
0x20005000 PROVIDE (__stack, __StackTop)
Но это больше зависит не от IDE, а от скрипта линкера. По умолчанию в EmBitz от так распределяет данные в ОЗУ и на мой взгляд довольно оптимально.
Re: Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 21:22:47
afz
VladislavS писал(а):Вы что-то конкретно путаете!
Блин, точно! Посыпаю голову пеплом. Виноват. Тогда действительно стоит разобраться, и что-то подкрутить Кейлу. Вопрос только
что именно?
Re: Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 21:29:15
VladislavS
[uquote="afz",url="/forum/viewtopic.php?p=3442511#p3442511"]Вопрос только что именно?[/uquote]Cтартап и скрипт линкера (scatter file в терминологии Keil).
Re: Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 21:33:19
afz
Это каждому проекту крутить, а хотелось бы поставить где-нибудь галочку, чтобы он делал это сам и для всех. Ну, в крайнем случае, ставить эту галочку каждому проекту...
Re: Распределение оперативной памяти в STM32
Добавлено: Чт авг 23, 2018 21:39:16
VladislavS
И кнопку "make happy".
Re: Распределение оперативной памяти в STM32
Добавлено: Пт авг 24, 2018 06:27:30
afz
Нет, одной мало. Дайте две!
И вообще, что за фигня? EmBitz же так делает, почему бы и Кейлу так не делать? Попробовать, что-ли, EmBitz?
Добавлено after 2 minutes 48 seconds:
Да, кстати, а где прописан прототип malloc() ? В "больших" системах я всегда писал #include <malloc.h>, а здесь (по крайней мере, у Кейла) такого файла нет...
Re: Распределение оперативной памяти в STM32
Добавлено: Пт авг 24, 2018 07:25:11
VladislavS
[uquote="afz",url="/forum/viewtopic.php?p=3442588#p3442588"]И вообще, что за фигня? EmBitz же так делает, почему бы и Кейлу так не делать?[/uquote]Вы что-то путаете. Keil делает ровно то что написано в вашем проекте. Куда поместите стек, там он и будет. Не делайте проблему там где её нет. У Кеил настоящих косяков полно, а вы ему ещё несуществующие приписываете.
[uquote="afz",url="/forum/viewtopic.php?p=3442588#p3442588"]Да, кстати, а где прописан прототип malloc() ? В "больших" системах я всегда писал #include <malloc.h>, а здесь (по крайней мере, у Кейла) такого файла нет...[/uquote]Всегда он в stdlib.h был.
Re: Распределение оперативной памяти в STM32
Добавлено: Пт авг 24, 2018 07:57:34
afz
Keil делает ровно то что написано в вашем проекте. Куда поместите стек, там он и будет.
Угу. Только EmBitz делает это сам, без моих движений, а Кейлу я должен буду править каждый проект, где мне нужно такое распределение памяти. И еще непонятно, как при этом бороться с кейловскими Stack_Size и Heap_Size - их же тоже придется регулярно править...
Re: Распределение оперативной памяти в STM32
Добавлено: Пт авг 24, 2018 11:00:38
VladislavS
У меня сложилось впечатление, что ни одного живого проекта ни в одной среде вы не сделали. Зато поговорить всегда пожалуйста. В любой среде программист должен держать под контролем распределение памяти. Если вы этого не хотите делать, то когда-нибудь всё равно огребёте.