|
IAR CSTACK RSTACK - измерение глубины стека |
|
|
|
Apr 19 2016, 07:56
|
Частый гость
 
Группа: Свой
Сообщений: 151
Регистрация: 19-12-04
Из: Москва
Пользователь №: 1 560

|
Цитата(zltigo @ Apr 19 2016, 10:33)  Смотреть на "1". И думать что происходит при возврате 1 функцией __low_level_init Хорошо в EWAVR_CompilerReference.pdf Код The value returned by __low_level_init determines whether or not data segments should be initialized by the system startup code. If the function returns 0 , the data segments will not be initialized. Намекаете на то что при возврате 1 сегмент инициализируется 0 по выходе из функции? А как же работает ASM вариант, который тоже возвращает 1 по той же ссылке? И раз уж пошел конструктивный диалог, давайте предположим что может дело в том что в С варианте затирается весь RSTACK а в ASM (SIZEOF RSTACK)-10) Может в этом дело?
|
|
|
|
|
Apr 19 2016, 08:04
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (Mty @ Apr 19 2016, 10:56)  Намекаете на то что при возврате 1 сегмент инициализируется 0 по выходе из функции? Или не затирается, зависит от того в какой секции линкеру указано размещать стеки. QUOTE Может в этом дело? Есественно, что из сишной (как и любой другой) функции которую ВЫЗВАЛИ и даже не первой в цепочке, полностью затирать стек ВОЗВРАТОВ нельзя. Затирать стек, инициализируя полностью можно только в стартапе, о чем сразу и писал. Чем вызвано Ваше такое дикое нежелание дописать несколько строк на ASM в стартапе?
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 19 2016, 08:30
|
Местный
  
Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682

|
Осторожнее надо быть с RSTACKом, потому что такой код его может подпортить: Код p = (char*)__segment_begin("RSTACK"); len = (size_t)__segment_end("RSTACK") - (size_t)__segment_begin("RSTACK"); while( len-- ) *p++ = 'R'; когда стартовый код вызывает __low_level_init, он заносит адрес возрата в RSTACK. отступите от __segment_end("RSTACK") на величину адреса возврата. И второе, Код char* p = (char*)__segment_begin("CSTACK"); использование локальных переменных может быть проблематичным и скорее всего будет. Наверняка при создании этой переменной компилятор задействует CSTACK
Сообщение отредактировал aiwa - Apr 19 2016, 08:40
|
|
|
|
|
Apr 19 2016, 11:17
|
Местный
  
Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682

|
Цитата Намекаете на то что при возврате 1 сегмент инициализируется 0 по выходе из функции? А как же работает ASM вариант, который тоже возвращает 1 по той же ссылке? В старапе код эквивалентен такому: Код if(_low_level_init()!=0) _segment_init(); // отредактирована ошибка Т.е. если _low_level_init вернула 0, то это означает, что программист желает, чтобы IAR произвел инициализацию сегментов, в противном случае программист берет эти процедуры на себя.
Сообщение отредактировал aiwa - Apr 19 2016, 11:46
|
|
|
|
|
Apr 19 2016, 13:29
|
Местный
  
Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682

|
Цитата(zltigo @ Apr 19 2016, 15:01)  Так и сделано  Что-то у меня с утра не заладилось. Я имел в виду возврат ненулевого значения означает знак ИАРу, что инициализация сегементов уже выполнена, а возврат 0 - выполнение инициализации ИАРом. Наподобие стандартной процедуры callback-функций, когда при возврате 0 производится стандартная процедура по умолчанию. Цитата(Mty @ Apr 19 2016, 15:32)  Насколько я понимаю он при инициализации сегментов не трогает стеки, а только загружает в DATA переменные? Порядок следующий: 1. в SP заносится значение конца RSTACKа, 2. в Y заносится значение конца СSTACKа, если разрешена внешняя память, то соответствующая аппаратная инициализация. Далее вызывается _low_level_init. Если она вернула ненулевое значение, то вызывается процедура инициализации сегментов _segment_init (Эта процедура уже написана на С.) И потом вызывается процедура построения статистических объектов классов.
|
|
|
|
|
Apr 20 2016, 00:12
|
Местный
  
Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682

|
Заинтересовало, по быстрому написал первоначальный вариант, но не проверял. CODE #pragma segment="RSTACK" static __no_init unsigned char a[1] @ "RSTACK"; typedef char ( *point_to_lowlevelinit)(void);
char __low_level_init() { register unsigned int count=__segment_size("RSTACK")-1; count-=sizeof(point_to_lowlevelinit);
while(count) { a[count]='R'; count--; } return 1; } Небольшие комментарии: 1. переменная а служит лишь меткой, для того чтобы компилятор занес в пару регистров начало RSTACKа По хорошему нужно брать значение из переменной SP, которая уже отступила от вершины стека на 1 адрес. 2. переменная count описана как register чтобы надеяться, что компилятор не трогал софт-стек. 3. определение point_to_lowlevelinit введено лишь для получения размера адреса возврата который уже занесен в стек - нужно отнять от это количество от count чтобы не затереть этот адрес. Здесь в документации лучше бы найти более подходящий способ, наверняка должны быть какие-то системные константы. Для заполнения софт-стека действуем аналогично. Еще бы нужно добавить через pragma отключение оптимизации для этой функции.
Сообщение отредактировал aiwa - Apr 20 2016, 00:37
|
|
|
|
|
Apr 20 2016, 08:57
|
Местный
  
Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682

|
Посмотрел с утра - код работать не будет. Не учел, что переменные ИАР располагает в сегментах от конца к началу, и что адресация флеш-памяти вдвое больше. Этот код прошел в отладчике: CODE char __low_level_init() { register char* point=(char*)SP; register char* pointtest=(char*)__segment_begin("RSTACK");
while(1) { *point='R'; point--; if(point<pointtest) break; } return 1; }
Для частных случаев работоспособен. P.S. оказалось, что первоначальный вариант тоже работал, сбило то , под сегмент стека ИАР выделил "страницу" памяти и сам стек занимал в нем лишь половину. В том примере нужно лишь добавть инициализацию a[0]='R';
Сообщение отредактировал aiwa - Apr 20 2016, 10:09
|
|
|
|
|
Apr 20 2016, 11:33
|
Частый гость
 
Группа: Свой
Сообщений: 151
Регистрация: 19-12-04
Из: Москва
Пользователь №: 1 560

|
Спасибо, круто! А вот интересно register char* point=(char*)SP; SP указывает на ПУСТУЮ ячейку или на ячейку с предыдущими данными? Иными словами при PUSH сначала копируется данные, а потом инкрементируется SP или наоборот?
Сообщение отредактировал IgorKossak - Apr 20 2016, 17:21
Причина редактирования: бездумное цитирование
|
|
|
|
|
Apr 20 2016, 13:27
|
Местный
  
Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682

|
Цитата(Mty @ Apr 20 2016, 14:33)  register char* point=(char*)SP; SP указывает на ПУСТУЮ ячейку или на ячейку с предыдущими данными? На пустую. Иначе бы затирался адрес возврата.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|