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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Передача управления из бута в программу, еще раз о старом
toweroff
сообщение Feb 25 2013, 10:57
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Добрый день

Вот такой вопрос возник. Управление передается через подобный вызов:
Код
void (*Entry_Point)(void);
Entry_Point = (void(*)(void))(USER_CODE);
Entry_Point();

кстати, еще вопрос сразу - для ядра ARM968E-S значение USER_CODE так же будет (REAL_USER_CODE + 1), как и для CM3?

Потом управление передается по адресу, указанному в линкере как ENTRY_POINT
Но вопрос вот какой. При старте процессора, он находится в Supervisor режиме, когда грузит все регистры, а из бута он попадет на точку входа приложения уже в User/System
Или это нормально, или я что-то не понял и проц нужно перед прыжком переводить в Supervisor режим?
Сколько пересмотрел реализаций бутов для ARM7, CM3 - нигде не увидел явной смены режима работы
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Feb 25 2013, 13:58
Сообщение #2


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(toweroff @ Feb 25 2013, 14:57) *
...нигде не увидел явной смены режима работы


по поводу режима - так-же не видел явно. возможно пока сильно не копал.
по поводу +1 = сам юзаю оверлейность, вычисление точки входа в "модуль" идёт на ран-тайме. управление передаётся на ура без всякой "коррекции" на единицу. объявление, вызов, сами подпрограммы - на сях.

кхм. как то загрузили блин sm.gif надо будет вкурить вопросы получше.
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Feb 25 2013, 14:05
Сообщение #3


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

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Цитата(toweroff @ Feb 25 2013, 14:57) *
для ядра ARM968E-S значение USER_CODE так же будет (REAL_USER_CODE + 1), как и для CM3?

Значение USER_CODE будет +1 или +0 в зависимости от того, ARM-код это, или THUMB.

Цитата(toweroff @ Feb 25 2013, 14:57) *
Или это нормально, или я что-то не понял и проц нужно перед прыжком переводить в Supervisor режим?
Сколько пересмотрел реализаций бутов для ARM7, CM3 - нигде не увидел явной смены режима работы

В моей реализации большими буквами написано "SWI и xxx_Handler не используется, надо инициализировать только пользовательский стек".
Но вообще-то для универсального бута странно. Это я знаю, что буду грузить своим загрузчиком.


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
toweroff
сообщение Feb 25 2013, 14:10
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(esaulenka @ Feb 25 2013, 18:05) *
Значение USER_CODE будет +1 или +0 в зависимости от того, ARM-код это, или THUMB.

только ARM

Цитата(esaulenka @ Feb 25 2013, 18:05) *
В моей реализации большими буквами написано "SWI и xxx_Handler не используется, надо инициализировать только пользовательский стек".
Но вообще-то для универсального бута странно. Это я знаю, что буду грузить своим загрузчиком.

SWI нет, все аборты заткнуты на одну функцию, которая выкидывает в канал связи состояние CPSR и адрес, вызвавший исключение
Go to the top of the page
 
+Quote Post
SyncLair
сообщение Feb 25 2013, 14:16
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 209
Регистрация: 6-01-12
Пользователь №: 69 197



Цитата(toweroff @ Feb 25 2013, 14:57) *
Сколько пересмотрел реализаций бутов для ARM7, CM3 - нигде не увидел явной смены режима работы

Режимы работы как правило инициализируются в самом загружаемом модуле. То есть типичный скрипт для запуска содержит
строчки где CPSR как раз инициализируется.


--------------------
Go to the top of the page
 
+Quote Post
toweroff
сообщение Feb 25 2013, 14:25
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата
Режимы работы как правило инициализируются в самом загружаемом модуле. То есть типичный скрипт для запуска содержит
строчки где CPSR как раз инициализируется.

ок, согласен. Но бут, как минимум, должен прерывания отключить, если он их использовал
тогда мне непонятен такой момент
На холодном старте проц вычитывает со стартового адреса
Код
ResetStart
    LDR     PC, ResetAddr
    LDR     PC, UndefinedAddr
    LDR     PC, SWI_Addr
    LDR     PC, PrefetchAddr
    LDR     PC, DataAbortAddr
    LDR     PC, ReservedAddr
    LDR     PC, IRQ_Addr
    LDR     PC, FIQ_Addr

далее инициализируются стеки (вызывается эта функция):
Код
InitStack    
    MOV     R0, LR
;Build the SVC stack
    MSR     CPSR_c, #SVC32Mode :OR: I_BIT :OR: F_BIT        
    LDR     SP, StackSvc    
;Build the IRQ stack
    MSR     CPSR_c, #IRQ32Mode :OR: I_BIT :OR: F_BIT
    LDR     SP, StackIrq
;Build the FIQ stack
    MSR     CPSR_c, #FIQ32Mode :OR: I_BIT :OR: F_BIT
    LDR     SP, StackFiq
;Build the DATAABORT stack
    MSR     CPSR_c, #ABT32Mode :OR: I_BIT :OR: F_BIT
    LDR     SP, StackAbt
;Build the UDF stack
    MSR     CPSR_c, #UDF32Mode :OR: I_BIT :OR: F_BIT
    LDR     SP, StackUnd
;Build the SYS stack
    MSR     CPSR_c, #SYS32Mode :OR: I_BIT :OR: F_BIT
    LDR     SP, =StackUsr
    MSR     CPSR_c, #SYS32Mode
    BX      R0


после чего прыгаем на __main

параметр __entry у линкера указывает именно на ResetStart

Так вот. Куда нужно прыгать? На сам ResetStart, или, все-таки, на точку вызова InitStack (точнее, на ResetStart+(4*8), ибо там может быть что-то еще, это у меня сразу стеки инициализируются и вызов InitStack оказывается размещенным по этому адресу)?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 25 2013, 14:43
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



На ResetStart, разумеется: его положение строго фиксировано.
Go to the top of the page
 
+Quote Post
toweroff
сообщение Feb 25 2013, 15:07
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(aaarrr @ Feb 25 2013, 18:43) *
На ResetStart, разумеется: его положение строго фиксировано.

Все, понял. Попадая на ResetStart, мы заносим в PC значение ResetAddr, по которому как раз лежит вызов инициализации стека и дальше как надо.
Остается один вопрос - инициализация обработчиков исключений, ведь этот блок мы просто пропустим, это не аппаратное вычитывание по холодному старту, а, фактически, просто двойной прыжок на ResetAddr
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 25 2013, 15:21
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(toweroff @ Feb 25 2013, 19:07) *
Остается один вопрос - инициализация обработчиков исключений, ведь этот блок мы просто пропустим, это не аппаратное вычитывание по холодному старту, а, фактически, просто двойной прыжок на ResetAddr

Если приложение не стартует по нулевому адресу (или адресу 0xffff0000 в случае HiVecs), то этот блок можно просто исключить за ненадобностью.
Просто бывает удобно его сохранить, когда приложение собирается как для случая работы с загрузчиком, так и для работы без оного.
Go to the top of the page
 
+Quote Post
toweroff
сообщение Feb 25 2013, 15:32
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(aaarrr @ Feb 25 2013, 19:21) *
этот блок можно просто исключить за ненадобностью.

это понятно!
непонятно другое - адреса, загруженные при старте, так и останутся адресами п/п бутлоадера. А если есть необходимость обработки их в основной программе?
я могу, конечно, разместить их в RAM по одинаковым адресам и в буте, и в приложении, но ведь это не гуд
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 25 2013, 15:38
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Вариантов масса:
- Использовать п/п загрузчика (в случае IRQ или FIQ это зачастую одна инструкция)
- Разместить адреса переходов в RAM
- Сделать remap
- Использовать верхние вектора
- Использовать MMU
Осуществимость последних трёх пунктов зависит от наличия поддержки со стороны ядра/системы.
Go to the top of the page
 
+Quote Post
toweroff
сообщение Feb 25 2013, 16:46
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



aaarrr, спасибо, пойду разбираться

Вот что накопал

Вектора располагаются в TCM памяти, когторая смаппирована на 0x00000000

То, что идет в примерай кейла, содержит вот такой ремап:
Код
    PRESERVE8

VECTOR_RAM_SRC    EQU        0x80000000
VECTOR_FLASH_SRC    EQU        0x20000000
VECTOR_DST        EQU        0x00000000

    EXPORT VectorRemap
    AREA BlockCopy, CODE, READONLY     ; name this block of code

VectorRemap
    STMFD   sp!, {r0, r1, r4-r11}; save registers
    IF :DEF: REMAP_RAM
    LDR     r0, =VECTOR_RAM_SRC
    ELSE
    LDR     r0, =VECTOR_FLASH_SRC; r0 = pointer to source block
    ENDIF
    LDR     r1, =VECTOR_DST        ; r1 = pointer to destination block      
    LDMIA   r0!, {r4-r11}        ; remap first 16 words from 0x20000000
    STMIA   r1!, {r4-r11}        ; to address 0x00000000 for interrupt
    LDMIA   r0!, {r4-r11}        ; exception handler
    STMIA   r1!, {r4-r11}  
    LDMFD   sp!, {r0, r1, r4-r11}; restore registers

    END

таким образом, в основной программе я могу переписать значения векторов в области 0x00000000 - 0x0000001F своими значениями... и все?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 25 2013, 16:55
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Выходит, все. Только я бы выделил вектора в отдельную секцию и размещал бы её на нулевом адресе штатными средствами (т.е. линкером). Подобные копирования только путаницу вносят.
Go to the top of the page
 
+Quote Post
toweroff
сообщение Feb 25 2013, 17:45
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(aaarrr @ Feb 25 2013, 20:55) *
Выходит, все. Только я бы выделил вектора в отдельную секцию и размещал бы её на нулевом адресе штатными средствами (т.е. линкером). Подобные копирования только путаницу вносят.

Embedded Flash по умолчанию маппируется из 0x20000000 на 0x00000000
Программа у меня собирается по физическому адресу. Фактически, хоть программа и "бегает" по реальным адресам, вектора лежат в маппированной области
Сейчас нужно разобраться, как вернуть отображение TCM памяти на свое реальное место и не очень понятно, как заставить линкер "положить" вектора в область нулевую
Точнее, КАК - это да, указать регион, но вот в каком месте это сделает ОН? скорее всего, в __main? Потому что копировать в отображаемую Flash не получится без отката ремапа
Да, вот еще вопрос какой. Как в кейле, в ASM файле указать регион, прописанный в скаттере?
Как-то так?
Код
        AREA    MyVectors, DATA, NOINIT, ALIGN=4

и в скаттере:
Код
LR_IROM1 0x20000000 0x00080000  {   ; load region size_region
  ER_IROM1 0x20000000 0x00080000  { ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_IRAM1 0x80000000 0x0000E000  { ; RW data
   *.o (RAMFUNC)
   .ANY (+RW +ZI)
  }
  RW_IRAM2 0x00000000 0x00008000 {; 16 KB TCM memory
   *.o (MyVectors)
  }
}
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Feb 25 2013, 18:45
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(toweroff @ Feb 25 2013, 21:45) *
...в каком месте это сделает ОН? скорее всего, в __main?

Да, в __main. До этого нужно настроить память.

Цитата(toweroff @ Feb 25 2013, 21:45) *
Как-то так?

Только вектора - они все же CODE, а не DATA.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 18th July 2025 - 22:02
Рейтинг@Mail.ru


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