|
Coocox настройка heap? |
|
|
|
Apr 16 2016, 14:51
|
Частый гость
 
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008

|
Не получается настроить кучу в coocox. По тем пример что на форуме http://www.coocox.org/forum/viewtopic.php?f=2&t=917 у меня не получилось. Во первых потому, что они с ошибками, а во вторых там не указано куда именно в файле *.ld нужна сделать вставку. В общем я сделал по другому: 1. В файле startup добавил Код /*----------Heap Configuration-----------------------------------------------*/ #define HEAP_SIZE 0x00001000 __attribute__ ((section(".heap"))) unsigned long pulHeap[HEAP_SIZE]; 2. В файле ld перенес сектор .heap который там уже был, под сектор .co_stack Код /* .stack_dummy section doesn't contains any symbols. It is only * used for linker to calculate size of stack sections, and assign * values to stack symbols later */ .co_stack (NOLOAD): { . = ALIGN(8); *(.co_stack .co_stack.*) } > ram
.heap (COPY): { __end__ = .; _end = __end__; end = __end__; *(.heap*) __HeapLimit = .; } > ram /* Set stack top to end of ram , and stack limit move down by * size of stack_dummy section */ __StackTop = ORIGIN(ram ) + LENGTH(ram ); __StackLimit = __StackTop - SIZEOF(.co_stack); PROVIDE(__stack = __StackTop); /* Check if data + heap + stack exceeds ram limit */ ASSERT(__StackLimit >= __HeapLimit, "region ram overflowed with stack") В файле syscalls.c вообще ничего не менял. Вот map файл который получился, и как видно из скриншота, функция calloc возвращает указатель именно из области сектора .heap Но только не пойму как работает ограничение, когда вылезаем за размеры кучи. Дело в том, что даже если я ставлю HEAP_SIZE 0x00000010. Программа работает но там явно память выделяется за границами кучи.
Сообщение отредактировал maxntf - Apr 16 2016, 15:02
Эскизы прикрепленных изображений
|
|
|
|
|
 |
Ответов
|
Apr 19 2016, 09:59
|
Частый гость
 
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008

|
Вух!!!, вроде все понял. Много вопросов отпало, когда собралась общая картинка. Просто начал я не с того боку и все из за того базового линк. Нужно было начинать с его ковыряния, а не кода Си. Вот линк: Код _eram = 0x20000000 + 0x00020000;
SECTIONS { .text : { KEEP(*(.isr_vector)) ля-ля-ля } > rom .data : { ля-ля-ля } > ram .bss : { ля-ля-ля } > ram
//Начало моей части где я настраиваю stack & heap //Стек _stack_size = 0x200;/*Размер - нужно только мне и для вычисления след. параметров*/ _StackTop = . + _stack_size;/*Вершина стека начало лок. данных + его размер*/ _StackLimit = .;/*Для наглядности - начало лок. данных*/ .stack :/*Это собственно секция стека*/ { . = . + _stack_size;/*установка размера этой секции*/ } > ram PROVIDE(_stack = _StackTop);/*значение _stack устанавливаем в _StackTop*/ /*_stack потом помещаем в начало вектора*/ //Куча _heap_size = 0x100;/*размер кучи*/ _heap_begin = _eram - _heap_size;/*адрес начала кучи*/ _heap_limit = _heap_begin + _heap_size;/*лимит кучи для проверки*/ .heap (_heap_begin):/*секцию под кучу располагаем адреса _heap_begin*/ { . = . + _heap_size;/*установка размера этой секции*/ } > ram } В startup файле устанавливаем только координаты начала стека, больше в нем нет ничего про стек и кучу! Код extern unsigned long _stack;//значение задано в линк. файле __attribute__ ((used,section(".isr_vector"))) void (* const g_pfnVectors[])(void) = { /*----------Core Exceptions------------------------------------------------ */ (void *)&_stack, /*!< The initial stack pointer */ Reset_Handler, /*!< Reset Handler */ NMI_Handler, /*!< NMI Handler */ Для проверки переполнения кучи в файле syscalls.c Код extern int _heap_begin; extern int _heap_limit; caddr_t _sbrk ( int incr ) { static unsigned char *heap = NULL; unsigned char *prev_heap; unsigned char *new_heap; if (heap == NULL) { heap = (unsigned char *)&_heap_begin; } prev_heap = heap; new_heap = heap + incr; if(new_heap > (unsigned char *)&_heap_limit) { return 0; } heap = new_heap; return (caddr_t) prev_heap; } По map файлу (просто для наглядности): В итоге мы получили стек размером 0x200 который идет с адреса 0x20000a88 к 0x20000888. Куча которая начинается с адреса 0x2001ff00 и идет до конца памяти с ограничением переполнения. Код COMMON 0x20000884 0x20000884 errno 0x20000888 . = ALIGN (0x4) 0x20000888 __bss_end__ = . 0x20000888 _ebss = __bss_end__ 0x00000200 _stack_size = 0x200 0x20000a88 _StackTop = (. + _stack_size) 0x20000888 _StackLimit = .
.stack 0x20000888 0x200 load address 0x080014b4 0x20000a88 . = (. + _stack_size) *fill* 0x20000888 0x200 0x20000a88 PROVIDE (_stack, _StackTop) 0x00000100 _heap_size = 0x100 0x2001ff00 _heap_begin = (_eram - _heap_size) 0x20020000 _heap_limit = (_heap_begin + _heap_size)
.heap 0x2001ff00 0x100 load address 0x08020b2c 0x2001ff00 _end = . 0x20020000 . = (. + _heap_size) *fill* 0x2001ff00 0x100 Остался один вопрос: Эти самые секции объявляются для того, чтоб в эти места памяти никто ничего левого не подсунул? Типа ка в линке MCC18 под ПИК когда нужна секция, в которую линкер ничего не суют? Цитата DATABANK NAME=bgpr2 START=0x500 END=0x6FF PROTECTED Или то-же только для наглядности? И здесь и так никто ничего не подсунет. Все глобальные переменные по порядочку по секциям data и bss (в PIC они были разбросаны по банкам памяти). Стек от А до В, куча от С до D. Все локальные переменные в стеке. Тогда может вообще лишнее объявлять эти секции? Сделать себе Код _stack_size = 0x200; _StackTop = . + _stack_size; PROVIDE(_stack = _StackTop); //Куча _heap_size = 0x100; _heap_begin = _eram - _heap_size; _heap_limit = _heap_begin + _heap_size; И Все?!
|
|
|
|
|
Apr 19 2016, 10:48
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(maxntf @ Apr 19 2016, 14:59)  В итоге мы получили стек размером 0x200 который идет с адреса 0x20000a88 к 0x20000888. Куча которая начинается с адреса 0x2001ff00 и идет до конца памяти с ограничением переполнения. Вы опять поменяли местами стек и кучу  Ну что же, если вам так нравится, то пусть будет так. Хотя мне больше по душе вариант, когда стек начинается в конце ОЗУ. Цитата(maxntf @ Apr 19 2016, 14:59)  Остался один вопрос: Эти самые секции объявляются для того, чтоб в эти места памяти никто ничего левого не подсунул? Если размер этих секций превысит свободное ОЗУ, то вы получите ошибку линковки. А так - да, можно и без этих секций, просто объявить _stack, _heap_begin и _heap_limit.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Apr 19 2016, 13:45
|
Частый гость
 
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008

|
Уважаемые AHTOXA и zltigo спасибо Вам за помощь! Цитата(AHTOXA @ Apr 19 2016, 13:48)  Вы опять поменяли местами стек и кучу  Ну что же, если вам так нравится, то пусть будет так. Хотя мне больше по душе вариант, когда стек начинается в конце ОЗУ. Если размер этих секций превысит свободное ОЗУ, то вы получите ошибку линковки. А так - да, можно и без этих секций, просто объявить _stack, _heap_begin и _heap_limit. Мне почему то больше понравился вариант сначала стек потом куча. Тогда исключается вариант их пересечения. Чтоб размер этих секций не превысил ОЗУ, я размер стека буду задавать какой нужен, а размер кучи все что осталось. А для контроля минимального размера кучи и сделаю условие в линкере. Код _StackSize = 0x1000;/*устанавливаем*/ _StackTop = . + _StackSize; PROVIDE(_stack = _StackTop); _HeapSize = _eram - _StackTop; _HeapBegin = _eram - _HeapSize; _HeapLimit = _eram; _HeapMinimal = 0x2000;/*устанавливаем*/ ASSERT(_HeapSize > _HeapMinimal, "warning! small size of the heap")
|
|
|
|
|
Apr 19 2016, 16:02
|
Частый гость
 
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008

|
Цитата(zltigo @ Apr 19 2016, 18:58)  Будет творится все, что угодно и описанный Вами вылет, но как частный случай. То есть не факт что программа обязательно вылетает в это прерывание?
|
|
|
|
|
Apr 19 2016, 17:30
|
Частый гость
 
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008

|
Цитата(zltigo @ Apr 19 2016, 19:14)  Программе порортили какие то данные. Например, переменная x станет вдруг равной 100500. Ну и? Да она вообще никуда вылетать не обязана. А может и вылететь по, практически любой причине. Просто у меня в отладке, когда указатель стека попадает в секцию bss сразу происходит вылет в то самое прерывание. Поскольку с прерываниями я еще не успел толком разобраться, вот и предположил что есть такая заглушка. Ну раз это не так, значит на данном этапе моих познаний ARM все равно как расположить стек и кучу (главное понял как  ). А дальше посмотрим.
Сообщение отредактировал maxntf - Apr 19 2016, 17:31
|
|
|
|
Сообщений в этой теме
maxntf Coocox настройка heap? Apr 16 2016, 14:51 AHTOXA Сначала вот вам картинка распределения ОЗУ:
начал... Apr 16 2016, 15:40 maxntf Цитата(AHTOXA @ Apr 16 2016, 18:40) нача... Apr 16 2016, 18:06  AHTOXA Цитата(maxntf @ Apr 16 2016, 23:06) Из ва... Apr 16 2016, 18:18  Lmx2315 Цитата(maxntf @ Apr 16 2016, 21:06) Во пе... Apr 16 2016, 18:40   maxntf Цитата(Lmx2315 @ Apr 16 2016, 21:40)
..г... Apr 16 2016, 19:04 maxntf Вроде пришло понимание части вопросов! Что при... Apr 18 2016, 12:01 zltigo QUOTE (maxntf @ Apr 18 2016, 15:01) [*] Э... Apr 18 2016, 12:13  maxntf QUOTE (zltigo @ Apr 18 2016, 15:13) Разум... Apr 18 2016, 12:34   zltigo QUOTE (maxntf @ Apr 18 2016, 15:34) Тогда... Apr 18 2016, 13:47 AHTOXA Цитата(maxntf @ Apr 18 2016, 17:01) - из ... Apr 18 2016, 13:49  maxntf Цитата(AHTOXA @ Apr 18 2016, 16:49) Непон... Apr 18 2016, 15:05   AHTOXA Цитата(maxntf @ Apr 18 2016, 20:05) С эти... Apr 18 2016, 16:43  zltigo QUOTE (AHTOXA @ Apr 19 2016, 13:48) Ну чт... Apr 19 2016, 11:06
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|