реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Что делает Си-код до main?
imiron13
сообщение Sep 28 2010, 06:57
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 22-02-09
Из: Минск
Пользователь №: 45 206



Немного почитал про это здесь:
http://infocenter.arm.com/help/index.jsp?t...i/Bce3gfea.html
(использую RVDS4)

Не совсем понятно с настройкой стека. Там пишут, что настройку стека выполняет пользовательский стартап код.
Я так и делаю, но еще до main библиотечная функция (sys_stackheap_outer) меняет указатель стека. Что это означает? Может ли библиотечный код пытаться настроить стеки сам? Я вроде даже не давал ему никакой информации о размещении памяти на МК.
Если из стартапа вызываю сразу main, то программа работает, но не инициализируются глобальные переменные. Но если я вызываю __main, то указатель стека изменяется и программа не доходит до main.

Также библиотечный код генерирует программное прерывание (SWI) с кодом 0x123456. Зачем это нужно?


Go to the top of the page
 
+Quote Post
sergeeff
сообщение Sep 28 2010, 07:09
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Никто не мешает вам переписать startup модуль под ваши потребности. То что у вас "не инициализируются" глобальные переменные свидетельствует о их неправильном размещении в памяти (сегмент data).
Go to the top of the page
 
+Quote Post
msalov
сообщение Sep 28 2010, 10:23
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045



Для корректного перехода в Main необходим текущий стек правильно настроить. Стартап помимо инициализации указателя на вершину стека инициализирует глобальные и статические переменные. Если вы пишете свой стартап - то должны реализовать необходимый минимум.
Go to the top of the page
 
+Quote Post
imiron13
сообщение Sep 28 2010, 11:27
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 22-02-09
Из: Минск
Пользователь №: 45 206



Цитата(gotty @ Sep 28 2010, 13:23) *
Для корректного перехода в Main необходим текущий стек правильно настроить. Стартап помимо инициализации указателя на вершину стека инициализирует глобальные и статические переменные. Если вы пишете свой стартап - то должны реализовать необходимый минимум.

Ну, на страничке, ссылку на которую я кидал, написано так:
Сначала вызывается начальный код пользователя, который должен:
- инициализировать указатели стеков
- настроить MMU/MPU
- настроить кэш/включить TCM

После должна вызываться __main из стандартной библиотеки Си . __main выполняет следующие действия:
-копирует код (?)
-копирует/распаковывает RW-данные (поэтому нет ничего удивительного, что когда я вызывал сразу main не инициализировались глобальные переменные)
-обнуляет неинициализированные данные

Далее вызывается __rt_entry, которая
- инициализирует библиотечные функции
- вызывает __user_initial_stackheap()
- вызывает $Sub$main()
В основном коде функции __user_initial_stackheap() и $Sub$main() я не переопределял, значит будут вызваны библиотечные. Там же написано, что если используется scatter-файл для линкера, то линкер создаст __user_initial_stackheap(). Scatter-файл я не использую. Что происходит в этом случае?
После этого вызывается main().

Проблема в том, что библиотечный код изменяет указатель стека и прога рушится. Изменение SP происходит в функции sys_stackheap_outer.



Go to the top of the page
 
+Quote Post
vallav
сообщение Sep 29 2010, 17:38
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 197
Регистрация: 8-04-05
Пользователь №: 3 977



Цитата(imiron13 @ Sep 28 2010, 15:27) *
Проблема в том, что библиотечный код изменяет указатель стека и прога рушится. Изменение SP происходит в функции sys_stackheap_outer.


У Вас до исполнения библиотечного кода SP имеет нужное Вам значение?
Чему оно равно и в каком месте присваивается SP?
В Keil для nxp176x сделано так - в стартапе под стек выделяется место в ОЗУ, адрес вершины этого блока ОЗУ и присваивается SP при исполнении
кода, который до main.
А сам код запускается так - делается переход из бутлоадера по адресу, равному значению первого слова во флеше.
В нулевое слово флеша обычно записывается это самое значение для SP, но значение нулевого слова нигде не используется.
Go to the top of the page
 
+Quote Post
imiron13
сообщение Sep 30 2010, 07:43
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 22-02-09
Из: Минск
Пользователь №: 45 206



Цитата(vallav @ Sep 29 2010, 20:38) *
У Вас до исполнения библиотечного кода SP имеет нужное Вам значение?
Чему оно равно и в каком месте присваивается SP?

Да до исполнения библиотечного кода все ок, вот этот кусочек стартапа(стартап самодельный: МК нестандартный) настраивает указатели стека (0x007fff0 - конец ОЗУ)

Код
isrReset
                ldr  r1, =0x007fff0                     ; SP для FIQ
                msr  cpsr_c, #(17 | 0xC0)          ; переход в режи FIQ
                mov  sp, r1
                sub  r1, r1, #1024                     ;FIQ_STACK_SIZE
                msr  cpsr_c, #(18 | 0xC0)         ; переход в режим IRQ
                mov  sp, r1
                sub  r1, r1, #1024                     ;IRQ_STACK_SIZE
                msr  cpsr_c, #(19 | 0xC0)         ; переход в режим Supervisor
                mov  sp, r1                            ; Supervisor SP

Теперь указатели стека имеют верные значения (0007FFF0-FIQ,0007FBF0-IRQ,0007F7F0-SV). Далее работа идет в режиме Supervisor. В конце стартапа:
Код
        ldr     R0, = __main
        BX      R0

Далее выполняется библиотечный код, который изменяет SP. Изменение происходит в функции sys_stackheap_outer (сверял адрес выполняемого кода в отладчике с map-файлом). Ситуация усложняется тем, что не знаю армовский асм, и не могу разобраться, что пытается сделать код, изменяющий SP. Кусочек, изменяющий SP на скрине (до выполнения mov sp,r0 в SP все еще верное значение; вообще-то SP сохраняется в R1, затем в SP возвращается значение из R1, но оно уже затерто). У меня ступор, буду оч благодарен за помощь и советы.
Прикрепленное изображение


Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
vallav
сообщение Sep 30 2010, 13:20
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 197
Регистрация: 8-04-05
Пользователь №: 3 977



Цитата(imiron13 @ Sep 30 2010, 11:43) *
Да до исполнения библиотечного кода все ок, вот этот кусочек стартапа(стартап самодельный: МК нестандартный) настраивает указатели стека (0x007fff0 - конец ОЗУ)

Далее выполняется библиотечный код, который изменяет SP. Изменение происходит в функции sys_stackheap_outer (сверял адрес выполняемого кода в отладчике с map-файлом). Ситуация усложняется тем, что не знаю армовский асм, и не могу разобраться, что пытается сделать код, изменяющий SP. Кусочек, изменяющий SP на скрине (до выполнения mov sp,r0 в SP все еще верное значение; вообще-то SP сохраняется в R1, затем в SP возвращается значение из R1, но оно уже затерто). У меня ступор, буду оч благодарен за помощь и советы.


То, что библиотечная функция при входе сохраняет старое значение стека а при выходе неправильно его восстанавливает -
такое врядли.
Я не знаю, как инициализация стека устроена в Вашем компиляторе.
В разных сделано по разному.
В некоторых - это нужно это делать самому.
В Keil - в вызове __main ( кода инициализации ) перед вызовом main ( самой программы ) стек инициализируется значением
_initial_sp, которое задается в стартапе при выделении блоков памяти.
Выглядит это так:

Stack_Size EQU 0x00000200

AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp

Может у Вас то же самое, но, так как в стартапе Вы этой метке значения не задали, что то идет не так.
У Вас стартап - с нуля самодельный?
А работающего стартапа из примеров ( который можно под свою прогу переделать ) нет?

Сообщение отредактировал vallav - Sep 30 2010, 13:22
Go to the top of the page
 
+Quote Post
Student Pupkin
сообщение Sep 30 2010, 15:58
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 328
Регистрация: 23-05-08
Пользователь №: 37 760



Цитата(imiron13 @ Sep 30 2010, 11:43) *
Теперь указатели стека имеют верные значения (0007FFF0-FIQ,0007FBF0-IRQ,0007F7F0-SV). Далее работа идет в режиме Supervisor. В конце стартапа:
Код
        ldr     R0, = __main
        BX      R0

А для System/User? Там кто SP настраивает? Можете Вы, а может и билиотечная функция (это как пожелаете):
Код
;  Enter User Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_SYS
                IF      :DEF:__MICROLIB

                EXPORT __initial_sp

                ELSE

                MOV     SP, R0
                SUB     SL, SP, #USR_Stack_Size
Кстати и вызов __main надо делать из System или User (в зависимости от того, в каком режиме Вы желаете быть при входе в main() smile.gif ... хотя в сказанном не уверен smile.gif).

Цитата(vallav @ Sep 30 2010, 17:20) *
В Keil - в вызове __main ( кода инициализации ) перед вызовом main ( самой программы ) стек инициализируется значением
_initial_sp, которое задается в стартапе при выделении блоков памяти.
Выглядит это так:

Stack_Size EQU 0x00000200

AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp

Сюдя по всему у топикстартера ARM7/ARM9, а не Cortex (как в LPC17xx)...

Сообщение отредактировал Student Pupkin - Sep 30 2010, 16:05
Go to the top of the page
 
+Quote Post
vallav
сообщение Sep 30 2010, 16:12
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 197
Регистрация: 8-04-05
Пользователь №: 3 977



Цитата(Student Pupkin @ Sep 30 2010, 19:58) *
Сюдя по всему у топикстартера ARM7/ARM9, а не Cortex (как в LPC17xx)...


И что?
Все компиляторы Си для ARM7/ARM9 предполагают явную установку стеков в стартапе?
У автора сделана явная и она портится...
Вот и появилось предположение, что это срабатывает неявная.
В Keil для кортекса - что бы Вы не делали с SP в стартапе, в main прога вывалится с SP, равным _initial_sp.
Go to the top of the page
 
+Quote Post
imiron13
сообщение Oct 1 2010, 07:00
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 22-02-09
Из: Минск
Пользователь №: 45 206



Кажется разобрался. Надо было написать функцию __user_initial_stackheap, которая возвращает вершину стека для основного режима, его границу, адрес кучи, ее границу. Заработало. Детали понимаю смутновато. Зачем библиотеке нужно перестраивать стек, и что она пыталась делать, когда я не писал эту функцию.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th June 2025 - 09:52
Рейтинг@Mail.ru


Страница сгенерированна за 0.0145 секунд с 7
ELECTRONIX ©2004-2016