|
Передача управления из бута в программу, еще раз о старом |
|
|
|
Feb 25 2013, 10:57
|

Гуру
     
Группа: Свой
Сообщений: 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 - нигде не увидел явной смены режима работы
|
|
|
|
|
Feb 25 2013, 13:58
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(toweroff @ Feb 25 2013, 14:57)  ...нигде не увидел явной смены режима работы по поводу режима - так-же не видел явно. возможно пока сильно не копал. по поводу +1 = сам юзаю оверлейность, вычисление точки входа в "модуль" идёт на ран-тайме. управление передаётся на ура без всякой "коррекции" на единицу. объявление, вызов, сами подпрограммы - на сях. кхм. как то загрузили блин  надо будет вкурить вопросы получше.
|
|
|
|
|
Feb 25 2013, 14:05
|

Профессионал
    
Группа: Свой
Сообщений: 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 не используется, надо инициализировать только пользовательский стек". Но вообще-то для универсального бута странно. Это я знаю, что буду грузить своим загрузчиком.
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Feb 25 2013, 14:10
|

Гуру
     
Группа: Свой
Сообщений: 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 и адрес, вызвавший исключение
|
|
|
|
|
Feb 25 2013, 14:16
|
Местный
  
Группа: Свой
Сообщений: 209
Регистрация: 6-01-12
Пользователь №: 69 197

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

Гуру
     
Группа: Свой
Сообщений: 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 оказывается размещенным по этому адресу)?
|
|
|
|
|
Feb 25 2013, 15:07
|

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

|
Цитата(aaarrr @ Feb 25 2013, 18:43)  На ResetStart, разумеется: его положение строго фиксировано. Все, понял. Попадая на ResetStart, мы заносим в PC значение ResetAddr, по которому как раз лежит вызов инициализации стека и дальше как надо. Остается один вопрос - инициализация обработчиков исключений, ведь этот блок мы просто пропустим, это не аппаратное вычитывание по холодному старту, а, фактически, просто двойной прыжок на ResetAddr
|
|
|
|
|
Feb 25 2013, 15:21
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(toweroff @ Feb 25 2013, 19:07)  Остается один вопрос - инициализация обработчиков исключений, ведь этот блок мы просто пропустим, это не аппаратное вычитывание по холодному старту, а, фактически, просто двойной прыжок на ResetAddr Если приложение не стартует по нулевому адресу (или адресу 0xffff0000 в случае HiVecs), то этот блок можно просто исключить за ненадобностью. Просто бывает удобно его сохранить, когда приложение собирается как для случая работы с загрузчиком, так и для работы без оного.
|
|
|
|
|
Feb 25 2013, 16:46
|

Гуру
     
Группа: Свой
Сообщений: 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 своими значениями... и все?
|
|
|
|
|
Feb 25 2013, 17:45
|

Гуру
     
Группа: Свой
Сообщений: 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) } }
|
|
|
|
|
Feb 25 2013, 18:45
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(toweroff @ Feb 25 2013, 21:45)  ...в каком месте это сделает ОН? скорее всего, в __main? Да, в __main. До этого нужно настроить память. Цитата(toweroff @ Feb 25 2013, 21:45)  Как-то так? Только вектора - они все же CODE, а не DATA.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|