Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Освоение ARM контроллеров
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2
maxntf
Тогда не верно выразился, нужно так - "Так все правильно будет работать?" . Учитывайте тот факт, что я вообще только начал изучение STM32.
И еще один вопрос в нагрузку:
- когда я ставлю в линкере основного проекта адрес 0x08001000, то после компиляции при переходе в отладку, у меня все весит по адресу 0x00000000. Ну это и понятно, потому что там ничего нет. Тогда как отлаживать? Сначала делаем программу как обычную не под бутлоадер, то есть не меняя в ней адрес таблицы векторов и не трогая линкер. А после того как проект готов, ставим в начало main SCB->VTOR = 0x08001000; и корректируем линкер. Или нужно что то еще?
scifi
Цитата(maxntf @ Apr 5 2016, 17:55) *
- когда я ставлю в линкере основного проекта адрес 0x08001000, то после компиляции при переходе в отладку, у меня все весит по адресу 0x00000000. Ну это и понятно, потому что там ничего нет. Тогда как отлаживать?

Я отлаживаю в кейле. Там можно подключить скрипт отладчика. В скрипте пишу
Код
SP = *(int*)0x08001000;
PC = *(int*)0x08001004;

И всё.
jcxz
Цитата(maxntf @ Apr 5 2016, 20:29) *
//здесь переопределение адреса таблицы векторов прерываний
//и переход к выполнению основной программы
__disable_irq ();
__set_MSP( *(uint32_t*)(0x08001000) );
SCB->VTOR = 0x08001000;
(*(void(*)(void))( *(uint32_t *)(0x08001000+4) ))();
}

Как-то слишком кудряво и лишнее разименование. Надо быть проще:
((void(*)(void))*(void **)0x08001004)();
И, как тут уже сказали, основная программа должна выставлять VTOR какой ей надо (как и все прочие регистры периферии), а не бутлоадер.
И какое-то у Вас странное содержимое SP. Вы уверены, что по этим адресам у Вас находится ОЗУ? Обычно в МК с ядром Cortex-M по этим адресам находится Flash.
И насчёт __disable_irq () - не уверен, что это будет работать в Cortex-M. Обычно для Cortex-M используют __disable_interrupt().
А __disable_irq() и __disable_fiq() - это для ARM7/9 (и Cortex-A наверное).

Цитата(maxntf @ Apr 5 2016, 19:32) *
Почитал про систему прерываний Cortex, она кардинально от PIC отличается но в принципе все понятно.

Кроме того: система прерываний Cortex-M кардинально отличается от системы прерываний Cortex-A.

Цитата(maxntf @ Apr 5 2016, 20:55) *
- когда я ставлю в линкере основного проекта адрес 0x08001000, то после компиляции при переходе в отладку, у меня все весит по адресу 0x00000000. Ну это и понятно, потому что там ничего нет. Тогда как отлаживать? Сначала делаем программу как обычную не под бутлоадер, то есть не меняя в ней адрес таблицы векторов и не трогая линкер

Это то как раз и непонятно. Что-то у Вас неправильно компилится/линкуется.
Не надо делать "не под бутлоадер". Если правильная конфигурация командного файла линкёра, то после загрузки ПО JTAG-ом, PC устанавливается на точку входа (содержимое вектора сброса или начало функции main()). И это вне зависимости от того, на какие адреса линковали - хоть в FLASH хоть в SRAM хоть во внешнюю SDRAM.
maxntf
Цитата(jcxz @ Apr 5 2016, 18:33) *
Это то как раз и непонятно. Что-то у Вас неправильно компилится/линкуется.
Не надо делать "не под бутлоадер". Если правильная конфигурация командного файла линкёра, то после загрузки ПО JTAG-ом, PC устанавливается на точку входа (содержимое вектора сброса или начало функции main()). И это вне зависимости от того, на какие адреса линковали - хоть в FLASH хоть в SRAM хоть во внешнюю SDRAM.

При установке в настройка линкера CooCox старт адреса 0x08001000, после компиляции и запуска отладки у меня во втором слове памяти по адресу 0x00000004 почему весит значение с адресом 0x00010101. Да и вообще я вижу, что в памяти какая то бяка вместо моей программы.
jcxz
Цитата(maxntf @ Apr 5 2016, 21:58) *
При установке в настройка линкера CooCox старт адреса 0x08001000, после компиляции и запуска отладки у меня во втором слове памяти по адресу 0x00000004 почему весит значение с адресом 0x00010101. Да и вообще я вижу, что в памяти какая то бяка вместо моей программы.

Так если линкуете с адреса 0x08001000, то зачем смотрите на адрес 0x00000000???
И что такое старт адрес 0x08001000? У Вас там таблица векторов прерываний расположена?
maxntf
Цитата(jcxz @ Apr 5 2016, 19:08) *
Так если линкуете с адреса 0x08001000, то зачем смотрите на адрес 0x00000000???
И что такое старт адрес 0x08001000? У Вас там таблица векторов прерываний расположена?


Смотрю на адрес 0x00000004 потому что внем записано 0x00010101 и у меня отладчик висит на этом адресе после старта.
Хотя смотрел бинарник после компиляции, там вроде все верно. (по крайней мере код программы есть)
Наверное я что то делаю не так.
Можете поэтапно указать все изменения проекта под бутлоадер от стандартного проекта, пусть даже который создаем через визар.
jcxz
Цитата(maxntf @ Apr 5 2016, 22:20) *
Хотя смотрел бинарник после компиляции, там вроде все верно. (по крайней мере код программы есть)
Наверное я что то делаю не так.

Как Вы смотрите бинарник? Как там видите адреса?
Смотреть надо map-файл. По нему проверяете куда у Вас скомпоновалась таблица векторов прерываний и прочие секции кода и данных.
Также там указана точка входа ПО (в IAR называется "Entry symbol"). Вот с этой точки входа отладчик и стартует.
Я не знаю кокос, пользуюсь IAR.
zltigo
QUOTE (jcxz @ Apr 5 2016, 18:33) *
Как-то слишком кудряво и лишнее разименование. Надо быть проще:

((void(*)(void))*(void **)0x08001004)();


1. #define ADDR 0x08001004
2. ()ADDR .... Будем явно тип преобразовывать
3. (*)ADDR ....В указатель
4, ((*)())ADDR .................. на функцию
5. ((*)(void))ADDR ........................................без параметров
6. (void(*)(void))ADDR ...... ничего не возвращающую

8. Ну и вызываем:

((void(*)(void))ADDR)();



jcxz
Цитата(zltigo @ Apr 5 2016, 22:43) *
1. #define ADDR 0x08001004
...
((void(*)(void))ADDR)();

У ТС адрес 0x08001004 - не адрес функции, а адрес вектора reset в таблице прерываний, который указывает на функцию. Так что там ещё разыменование забыли.
А если-б это был адрес функции, бит0 был бы равен ==1, а не 0.
zltigo
QUOTE (jcxz @ Apr 5 2016, 19:50) *
У ТС адрес 0x08001004 - не адрес функции, а адрес вектора reset в таблице прерываний, который указывает на функцию.

Поял.
QUOTE
А если-б это был адрес функции, бит0 был бы равен ==1, а не 0.

Это смотря какой режим - не только на кортексах свет клином сошелся.
maxntf
Цитата(jcxz @ Apr 5 2016, 19:37) *
Как Вы смотрите бинарник? Как там видите адреса?

Не адреса я смотрю в отладчике, а в бинарнике вижу что он совсем отличается от того что выдаёт отладчик. Данные с бинарника похожие на то что в отладчике только когда я собираю проект без смещения.
scifi
Цитата(zltigo @ Apr 5 2016, 19:56) *
Это смотря какой режим - не только на кортексах свет клином сошелся.

Здесь сошёлся. По некоторым признакам, у него Cortex-M4. Если ему ещё про что-то другое вещать, совсем зависнет laughing.gif
Kabdim
Афаик нужно после смены адреса таблицы прерываний надо всадить DSB для повышения кошерности.
maxntf
Цитата(scifi @ Apr 5 2016, 18:10) *
Я отлаживаю в кейле. Там можно подключить скрипт отладчика. В скрипте пишу
Код
SP = *(int*)0x08001000;
PC = *(int*)0x08001004;

И всё.

А где именно это можно сделать, можно подробнее?
scifi
Цитата(maxntf @ Apr 9 2016, 10:36) *
А где именно это можно сделать, можно подробнее?

В свойствах проекта во вкладке "отладчик" можно указать файл скрипта инициализации. Можно назвать файл "debug.ini", и в нём всё это написать.
У меня линия RESET от отладчика к МК не подключена, поэтому я вместо загрузчика ставлю заглушку типа "while (1) {}". После сброса МК втыкается в эту заглушку, потом подключается отладчик и принимает дела.
maxntf
Подключил FreeRTOS, пока практически пустой проект 3 задачи для теста - 1-я контроль кнопки, 2-я передача строки "Hello World" в UART и 3-я мигание индикаторами.
Хотя в FreeRTOSConfig.h и стоит #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 75 * 1024 ) ) , но в SRAM забрало очень много места, почти 60% всей ОЗУ.
Цитата
Program Size:
12440 28 79288 91756 1666c main.elf
text data bss dec hex filename

Подскажите почему так? Смотрел в map файле я так понимаю что все жрет heap_2.c
Цитата
*fill* 0x200001aa 0x6
.bss 0x200001b0 0x12c14 ..\obj\heap_2.o
*(COMMON)
COMMON 0x20012dc4 0xe ..\obj\main.o
Сергей Борщ
QUOTE (maxntf @ Apr 12 2016, 17:09) *
Подскажите почему так?
75 * 1024 = 76800 = 0x12C00
maxntf
Блин сам и напоролся. Смотрел конфиг из чужого проекта, там было #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) ). А то что у меня 75 стоит и не обратил внимания!
zltigo
QUOTE (maxntf @ Apr 12 2016, 18:09) *
Смотрел в map файле я так понимаю что все жрет heap_2.c

Вообще в идеале heap должен занимать ВООБЩЕ ВСЮ свободную память. Посему любые константные дефиниции его размера в корне порочны. Следует слегка постараться и отдавать хипу всю память от конца статически распределенной компилятором до конца памяти контроллера.
AVI-crak
Цитата(zltigo @ Apr 12 2016, 23:13) *
Следует слегка постараться и отдавать хипу всю память от конца статически распределенной компилятором до конца памяти контроллера.


Интересно, каким способом???
Я например точно знаю что GCC не умеет считать размер стека прерываний в режиме перепроцессора. Уже потом в отладке, фоновым процессом самого отладчика контролируется нижняя граница, и только в одном режиме ядра - для ос это уже недоступно. Копал долго и упорно, но возможно что-то упустил.

Для себя эту проблему решил простым способом: heap условно растёт в верх, на встречу стеку. Условно, потому-что свой heap, для gcc он нулевой, используется только точка старта. При заполнении всей памяти - новые задачи и новый маллок морозится, пока жирность не спадёт. Очень удобно однако.
zltigo
Цитата(AVI-crak @ Apr 12 2016, 20:14) *
Интересно, каким способом???

Как и любое выделение памяти.
Цитата
Я например точно знаю что GCC не умеет считать размер стека прерываний в режиме перепроцессора. Уже потом в отладке, фоновым процессом самого отладчика контролируется нижняя граница, и только в одном режиме ядра - для ос это уже недоступно. Копал долго и упорно, но возможно что-то упустил.

Подумате головой и выделите именно стеку фиксированный размер памяти. Отдавать стеку ВСЕ свободное пространство, причем НИКАК его размер не контролировать в надежде, что хватит, это безумие.
Цитата
Для себя эту проблему решил простым способом: heap условно растёт в верх, на встречу стеку.

Навстречу чему, это уже зависит только от Вас, поскольку где Вы расположите стеки(и) там они они и будут.
У меня системные стеки внизу.
Цитата
Условно, потому-что свой heap, для gcc он нулевой, используется только точка старта.

Нулевой это перебор. Можно указать в для статической линковки какой-то минимальный размер для старта системы. Потом уже при запуске узанать верхнюю границу памяти и сказать мереждеру, что от начала статически слинковоного блока и до конца свободной памяти все его.
Пример распределения памяти для ARM7
CODE
define symbol Code_start = 0x00000000;

// Memory Regions -----------------------------------------------------------
// 256K ROM memory
define symbol ROM_start = 0x00000000;
define symbol ROM_end = 0x00007FFF;
// 16K RAM memory
define symbol RAM_start = 0x40000000;
define symbol RAM_end = 0x40001FFF;

// Memory Block Sizes
define symbol SIZE_CSTACK = 0x20; // Dummy System/User Stack Size (Not Used!)
define symbol SIZE_SVCSTACK = 0x180; // Supervisor Mode (Main Work Mode)
define symbol SIZE_IRQSTACK = 0x200;
define symbol SIZE_FIQSTACK = 0x40; //
define symbol SIZE_XXXSTACK = 0x20; // 32bytes Shared Stack for Abort/Undefined Instruction and IAP Buffer
define symbol SIZE_HEAP_RTOS = 0x400; // 1Kb - Dummy _minimal_ space for Memory Manager

define memory mem with size = 4G;
define region ROM = mem:[from ROM_start to ROM_end];
define region RAM = mem:[from RAM_start to RAM_end - SIZE_XXXSTACK];
define region RAM_endblock = mem:[from RAM_end - SIZE_XXXSTACK + 1 to RAM_end];

define block CSTACK with alignment=8, size = SIZE_CSTACK { };
define block SVC_STACK with alignment=8, size = SIZE_SVCSTACK { };
define block IRQ_STACK with alignment=8, size = SIZE_IRQSTACK { };
define block FIQ_STACK with alignment=8, size = SIZE_FIQSTACK { };
define block HEAP_RTOS with alignment=8, size = SIZE_HEAP_RTOS { };
define block XXX_BLOCK with alignment=8, size = SIZE_XXXSTACK { };
define block CHECKSUM { readonly section .checksum };

initialize by copy { readwrite };
do not initialize { section .noinit };

place in ROM { readonly section .intvec };
place in ROM { readonly };
place in ROM { block CHECKSUM };

place in RAM { readwrite,
block CSTACK, block SVC_STACK, block IRQ_STACK, block FIQ_STACK };
place in RAM { block HEAP_RTOS };

place in RAM_endblock {
block XXX_BLOCK };
AVI-crak
Цитата(zltigo @ Apr 13 2016, 01:49) *
Как и любое выделение памяти.

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


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

Хотя я надеялся увидеть хитрую трёхэтажную запись мнемониками перепроцесора самого GCC.
zltigo
QUOTE (AVI-crak @ Apr 13 2016, 00:39) *
Ну я и вижу как вы мучаетесь, в ручном режиме считая байты.

Это Вы маятесь дурью НЕ задавая размера стека в безосновательной надежде, на то, что он не наедет на кучу.
QUOTE
Хотя я надеялся увидеть хитрую трёхэтажную запись мнемониками перепроцесора самого GCC.

Надежды на чудесные, но нереальные решения и прочие авось, не к лицу инженерам. Размеры стеков придется придется оценивать, указывать и контролировать.
AVI-crak
Цитата(zltigo @ Apr 13 2016, 04:52) *
Это Вы маятесь дурью НЕ задавая размера стека в безосновательной надежде, на то, что он не наедет на кучу.


Желаю вам научится читать чужие сообщения.
zltigo
QUOTE (AVI-crak @ Apr 13 2016, 03:41) *
Желаю вам научится читать чужие сообщения.

Именно по тому, что не только читал, но и ПОНЯЛ, и написал, что Ваш "метод" не решает ничего. И в примере своем не просто так ARM7 привел с его множеством стеков (то же самое и старшие кортексы) при котрых Ваша идея, что размер стека сам собой устаканитися и думать о его размере не надо, вообще не пригодна в принципе. Собственно все у Вас работает только по причине что У Вас пока явный избыток памяти всегда.
jcxz
Цитата(zltigo @ Apr 12 2016, 22:13) *
Вообще в идеале heap должен занимать ВООБЩЕ ВСЮ свободную память. Посему любые константные дефиниции его размера в корне порочны. Следует слегка постараться и отдавать хипу всю память от конца статически распределенной компилятором до конца памяти контроллера.

ЗАЧЕМ??? ...если куча не нужна и не используется нигде в проекте.
Во всех моих проектах размер кучи задан ==0 в конфигурационном файле компоновщика.
У меня везде так (для IAR):
Код
define block CSTACK with alignment = 8, size = 0x000 {};
define block HEAP   with alignment = 8, size = 0x000 {};

А далее:
Код
do not initialize  {section .bssStk};
do not initialize  {section .bssStkMain};
...
place in RAM_regionA {section .BITBAND_RAM, section .dma, section .ethernet};
place in RAM_regionA {rw, first block CSTACK, section .bssMemNoFill, block HEAP};

Стеки задач, основной стек (который указан в reset-векторе) и стек исключений определены подобно:
Код
#pragma data_alignment = 8
__no_init static OS_STK taskADEStk[64 + STK_SIZE_ISR_NFP] @ ".bssStk";

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

PS: Контролировать размер стеков конечно нужно. И выделять под них память, а не надеяться что "что-то не налезет на что-то".
zltigo
QUOTE (jcxz @ Apr 13 2016, 09:10) *
ЗАЧЕМ??? ...если куча не нужна и не используется нигде в проекте.

Ну вообще-то, совершенно очевидно, речь идет о случае, когда куча используется.




QUOTE (jcxz @ Apr 13 2016, 09:10) *
Имхо: определять размеры стеков в си-шных файлах гораздо удобнее, чем в едином конфигурационном файле компоновщика.

Чем? Есть одно место, где описаны все размеры блоков памяти конкретного проекта. Заходишь и смотришь, а не надо ползать искать. Когда пишутся, например, всякие демки на 999 вариантов, тогда в них приходится выносить и размазывать настройки по файлам и ключам. Но для конкретного проекта зачем?
ViKo
Как можно контролировать стек (не задач в RTOS), который растет себе и растет, пока не налезет на кучу или переменные??
zltigo
QUOTE (ViKo @ Apr 13 2016, 10:25) *
Как можно контролировать стек (не задач в RTOS), который растет себе и растет, пока не налезет на кучу или переменные??

Также, как и "задач в RTOS". Какие проблемы? Те стеки тоже "растут себе и растут"... С контролем НЕ в реальном массштабе времени проблем нет. Но вот именно отсутствие контроля в реальном времени как раз и не позволяет на ходу разруливать ситуации со стеком и следовательно по любому под стек нужно выделять гарантированно достаточное место. Потом уже постфактум по результатам контроля, если надо, думать уменьшить его или нет.
jcxz
Цитата(zltigo @ Apr 13 2016, 12:27) *
Чем? Есть одно место, где описаны все размеры блоков памяти конкретного проекта. Заходишь и смотришь, а не надо ползать искать. Когда пишутся, например, всякие демки на 999 вариантов, тогда в них приходится выносить и размазывать настройки по файлам и ключам. Но для конкретного проекта зачем?

Есть задача, у неё свой стек. Все переменные, дефайны этой задачи - в её файлах. Проект состоит из множества таких задач. Естественно что данные, нужные локально только данной задаче, должны быть локальны (описаны именно в её файлах, а не вкаком-то едином файле). А стек - это локальная сущность конкретной задачи. И размер его скорее зависит от данной задачи, а не от проекта в целом.
Или Вы и локальные переменные каждой задачи тоже в едином файле определяете? laughing.gif
zltigo
QUOTE (jcxz @ Apr 13 2016, 11:43) *
Есть задача, у неё свой стек.

Не передергивайте! Речь идет о статически распределяемой памяти.
Но, если-бы я с какого-то бодуна выделял стеки задачам статически, то, да и эти БЛОКИ памяти я бы ТОЖЕ описал под линкер, что-бы видеть общую картину в одном месте и сразу при проектировании, а не тогда, кода линкер выругается при линковке что памяти совсем нет. После чего придется ползать по куче файлов и думать где жертвовать.
QUOTE
А стек - это локальная сущность конкретной задачи.

Содержимое стека - несомненно. Но сам стек, как блок памяти, это уже элемент ВЕРХНЕГО, надзадачного уровня. Вот и его выделением и размещением занимается НЕ задача.
QUOTE
Или Вы и локальные переменные каждой задачи тоже в едином файле определяете? laughing.gif

К чему эта дурацкая фраза и усмешка?
jcxz
Цитата(zltigo @ Apr 13 2016, 13:50) *
Также, как и "задач в RTOS". Какие проблемы? Те стеки тоже "растут себе и растут"... С контролем НЕ в реальном массштабе времени проблем нет. Но вот именно отсутствие контроля в реальном времени как раз и не позволяет на ходу разруливать ситуации со стеком и следовательно по любому под стек нужно выделять гарантированно достаточное место. Потом уже постфактум по результатам контроля, если надо, думать уменьшить его или нет.

В принципе - можно и в реальном. И даже под многозадачную ОС.
С MMU конечно вообще проблем нет такое сделать. Но даже с MPU это возможно. Я уже не раз задумывался чтобы внести такую функциональность в свои проекты, всё руки не доходят.
Как:
Вынести все стеки задач в единый сплошной сегмент памяти. Закрыть полностью доступ к этому сегменту через MPU. В ISR PendSV при каждом переключении пользовательского контекста, программировать перекрывающую запись таблицы MPU (более приоритетную чем та запись, которая закрывает доступ ко всему сегменту стека) на новый стек (находящийся внутри общего сегмента стека).
Конечно будут потери памяти на выравнивании, необходимом для MPU. Но сделать вроде можно.
Да - в начале и в конце сегмента стека должны быть небольшие интервалы неиспользуемой памяти.
Конечно, если функция внутри задачи написана так, что выделяет размер массива выходящий за границу сегмента стека, то тогда такая защита может не спасти. Но чаще всего доступ к стеку идёт более-менее последовательно, небольшими шагами.

Цитата(zltigo @ Apr 13 2016, 15:01) *
Если-бы я с какого-то бодуна выделял стеки задачам статически, то, да и эти БЛОКИ памяти я бы ТОЖЕ описал для линкера.

А с какого бодуна Вы выделяете стеки задачам динамически? И зачем такое делать? Задачи создавать/убивать? Это лишнее.
zltigo
QUOTE (jcxz @ Apr 13 2016, 12:05) *
А с какого бодуна Вы выделяете стеки задачам динамически? И зачем такое делать? Задачи создавать/убивать? Это лишнее.

Без комментариев, ибо рожденный ползать понять "лишнего" не может sad.gif
jcxz
Цитата(zltigo @ Apr 13 2016, 15:01) *
Вот и его выделением и размещением занимается НЕ задача.

Размещением стека, как и любой другой статической переменной у меня занимается компоновщик. Не вижу ни малейшего смысла выделять стек динамически.
Какая разница кто размещает?
Есть разница где эта переменая описана. А описана она должна быть там же, где и прочие локальные переменные задачи.

Цитата(zltigo @ Apr 13 2016, 15:08) *
Без комментариев, ибо рожденный ползать понять "лишнего" не может sad.gif

Думаю, что во всех случаях, когда нужно зачем-то создавать/убивать задачи в embedded среде с заранее известным выполняемым функционалом (речь не идёт о системах, в которых заранее не известен список работающих задач, когда задачи запускаются пользователем), всегда можно составить максимальный список задач, которые могут работать одновременно, выделить под них стеки статически и все их запустить.
И не убивать их когда работа закончена и создавать заново, а просто приостанавливать выполнение когда необходимо (на мэйлбоксе например), до появления новых данных для обработки.
KnightIgor
Цитата(jcxz @ Apr 13 2016, 07:10) *
PS: Контролировать размер стеков конечно нужно. И выделять под них память, а не надеяться что "что-то не налезет на что-то".

Если опустить RTOSы и MMU/MPU.- а такие системы с супер циклом просты и весьма популярны, - то контроль стека организовать затратно, и риск проехать катком стека по переменным есть. Это неизбежно.
На мой взгляд, в системе со стеком И кучей следует именну кучу выделять фиксированного размера, а стек - сколько есть памяти. Почему? Оценить потребность в стеке гораздо сложнее, чем в куче: прерывания, рекурсии, сложно-предсказуемые глубины вызовов... А вот работа с кучей более детерминирована и подконтрольна. Например, в тех немногих местах, где она используется, легко проверить полученный от malloc указатель на NULL и ругнуться, если что не так... Стек же я инициализирую на самый верхний адрес доступной RAM памяти. Как это в .COM программах в DOS делалось cool.gif (я стар, о я очень стар, я - суперстар!).
jcxz
Цитата(KnightIgor @ Apr 13 2016, 15:20) *
Например, в тех немногих местах, где она используется, легко проверить полученный от malloc указатель на NULL и ругнуться, если что не так...

Если есть куда ругнуться. А если ни LCD ни UART с терминалом? Да и вообще - ближайший человек за тыщу км laughing.gif
zltigo
QUOTE (jcxz @ Apr 13 2016, 12:19) *
И не убивать их когда работа закончена и создавать заново, а просто....

Когда о количестве ресурсов можно не думать, то оно, конечно, все "просто". Просто берем больше памяти, мегагерцев, размеров корпуса и батареи.





QUOTE (jcxz @ Apr 13 2016, 12:25) *
Если есть куда ругнуться. А если ни LCD ни UART с терминалом? Да и вообще - ближайший человек за тыщу км laughing.gif

Значит есть какая-то связь с чем-то, или человек за тысячу километров приедет хоть когда-то и увидит хоть в какой-то энергонезависимой памяти зафиксированную ошибку. Что уже позволит начать думать над тем, что в коде есть проблемы.
MrYuran
Цитата(jcxz @ Apr 13 2016, 12:25) *
Если есть куда ругнуться. А если ни LCD ни UART с терминалом? Да и вообще - ближайший человек за тыщу км laughing.gif

Тогда можно ругнуться в себя.
zltigo
QUOTE (KnightIgor @ Apr 13 2016, 12:20) *
Стек же я инициализирую на самый верхний адрес доступной RAM памяти. Как это в .COM программах в DOS делалось cool.gif (я стар, о я очень стар, я - суперстар!).

Я едва-ли Вас моложе, но так уже не делаю sm.gif, тем более, что не у x86 этих самых стеков чаще всего не один sm.gif
maxntf
Подскажите во время отладки в CoIDE где можно узнать адреса по которым расположены переменные?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.