Цитата(mronetwo @ May 24 2012, 14:06)

Не мало.Ппросто чтобы не затирать его (ну не увидел я что ему sp так легко переинитить) расположить в конце, а приложение в начале и при загрузке подменять приложению вектор ресета. Вариант такой был неудачный.
Тут как раз недавно написал загрузчик под наши нужды. Основные параметры: расположен в первых 16K памяти, считывает прошивку с SD-карты, приложение должно располагаться выше 16K (то есть, загрузчик присутствует всегда).
О стеке.
В приложениях я располагаю его в самом верху имеющегося RAM. Для этого я модифицирую ассемблерный startup файл. Например:
Код
IF :DEF: RAM_SIZE
__initial_sp EQU 0x20000000+RAM_SIZE*1024
Stack_Mem EQU __initial_sp - Stack_Size
ELSE
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
ENDIF
Определение RAM_SIZE=48 (48кБ для STM32F103RC) находится в опциях всего проекта (KEIL).
О приложении.
Приложение "отсылается" на 16кБ выше, за загрузчик, с помощью SCATTER файла компоновщика:
Код
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
;
; V1.0:
; This scatter file is modified to allocate the main section
; at 0x4000 (16kB) boundary while the reflashable settings
; constants - at the end of the image (256K-2K, for
; STM32F103RC).
;
; FlashSize = 0x00040000 (256K):
;
; BOOT_LOADER @ 0x08000000 .. 0x08003FFF, size 0x4000
; USER_CODE @ 0x08004000 .. 0x0803F7FF, size 0x40000-0x4000-0x800
; B_ARC_C_PARAMS @ 0x0803F800 .. 0x0803FBFF, size 0x400
; B_ARC_C_USB@ @ 0x0803FC00 .. 0x0803FFFF, size 0x400
;
;
LR_IROM2 (0x08000000 + 0x4000) (0x40000-0x4000-0x800) {; load region size_region
ER_IROM2 (0x08000000 + 0x4000) (0x40000-0x4000-0x800) {; load address = execution address
*.o (USER_VECTORS, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x0000C000 {; RW data
.ANY (+RW +ZI)
}
}
LR_IROM3 (0x08000000 + (0x00040000-0x800)) 0x800 {; load region size_region
ER_IROM3 (0x08000000 + (0x00040000-0x800)) 0x400 {; load address = execution address
*(B_ARC_C_PARAMS)
}
ER_IROM4 (0x08000000 + (0x00040000-0x400)) 0x400 {; load address = execution address
*(B_ARC_C_USB)
}
}
На LR_IROM3 можно не обращать внимание, - это наша "примочка" хранить установки в последней странице флэша.
startup.s имеет имя секции векторов (USER_VECTORS) согласованое со "скатертью" выше:
Код
; Future user program vector table
AREA USER_VECTORS, DATA, READONLY, ALIGN=9; 2^9=512
EXPORT __Vectors
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD ...
DCD ...
Загрузчик переходит на основное приложение с помощью кода ниже (который для удобства размещен в startup.s загрузчика, чтобы не порождать новый *.s файл):
Код
VTOR EQU (0xE000E000 + 0x0D08)
StartMainApp PROC; R0 - parameter with the APP vector table address
EXPORT StartMainApp [WEAK]
MOV32 R1, #VTOR ; Load VTOR register address
STR R0, [R1] ; Store to VTOR to relocate the vector table
LDR SP, [R0] ; Reinit the user stack
LDR R0, [R0, #4] ; Get the user entry point...
BX R0 ; ... and jump to it
ENDP
Код:
1). принимает в R0 адрес загрузки приложения, что есть по сути адрес таблицы векторов.
2). Переназначает VTOR на эту таблицу
3). считывает из таблицы (первое ее слово) значение стека и инициализирует указатель стека
4). считывает второе слово из таблицы, что и есть адрес начала исполняемой программы, и переходит на нее.
Вызов его осуществляется как:
extern void StartMainApp(void *app);
StartMainApp((void*)LoadAddressOfApp);
В конкретном случае LoadAddressOfApp равно тупо 16K.