228 bl hal_mmu_init
此前内存初始化好了,sp也设置好了,可以运行C程序
170 void
171 hal_mmu_init(void)
172 {
173 unsigned long ttb_base = SMDK2410_SDRAM_PHYS_BASE + 0x4000;
174 unsigned long i;
175
176 // Set the TTB register
177 asm volatile ("mcr p15,0,%0,c2,c0,0" : : "r"(ttb_base) );
178
179 // Set the Domain Access Control Register
180 i = ARM_ACCESS_TYPE_MANAGER(0) |
181 ARM_ACCESS_TYPE_NO_ACCESS(1) |
182 ARM_ACCESS_TYPE_NO_ACCESS(2) |
183 ARM_ACCESS_TYPE_NO_ACCESS(3) |
184 ARM_ACCESS_TYPE_NO_ACCESS(4) |
185 ARM_ACCESS_TYPE_NO_ACCESS(5) |
186 ARM_ACCESS_TYPE_NO_ACCESS(6) |
187 ARM_ACCESS_TYPE_NO_ACCESS(7) |
188 ARM_ACCESS_TYPE_NO_ACCESS(8) |
189 ARM_ACCESS_TYPE_NO_ACCESS(9) |
190 ARM_ACCESS_TYPE_NO_ACCESS(10) |
191 ARM_ACCESS_TYPE_NO_ACCESS(11) |
192 ARM_ACCESS_TYPE_NO_ACCESS(12) |
193 ARM_ACCESS_TYPE_NO_ACCESS(13) |
194 ARM_ACCESS_TYPE_NO_ACCESS(14) |
195 ARM_ACCESS_TYPE_NO_ACCESS(15);
196 asm volatile ("mcr p15,0,%0,c3,c0,0" : : "r"(i) );
197
198 // First clear all TT entries - ie Set them to Faulting
199 memset((void *)ttb_base, 0, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE);
200
201 // Memory layout after MMU is turned on
202 //
203 // SDRAM_BASE_ADDRESS: 0x00000000, 64M
204 // SRAM_BASE_ADDRESS: 0x40000000, 4K
205 // SFR_BASE_ADDRESS: 0x48000000, 512M
206 // FLASH_BASE_ADDRESS: 0x80000000, 2M
207
208 //Actual Virtual Size Attributes Function
209 //Base Base MB cached? buffered? access permissions
210 // xxx00000 xxx00000
211 X_ARM_MMU_SECTION(0x000, 0x800, 2, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); // Flash
212 X_ARM_MMU_SECTION(0x300, 0x000, 64, ARM_CACHEABLE, ARM_BUFFERABLE, ARM_ACCESS_PERM_RW_RW); // SDRAM
213 X_ARM_MMU_SECTION(0x400, 0x400, 1, ARM_CACHEABLE, ARM_BUFFERABLE, ARM_ACCESS_PERM_RW_RW); // SRAM
214 X_ARM_MMU_SECTION(0x480, 0x480, 512, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); // SFRs
215 X_ARM_MMU_SECTION(0x300, 0x300, 64, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); // Raw SDRAM
216 }
还有
#define SMDK2410_SDRAM_PHYS_BASE 0x30000000
#define SMDK2410_SDRAM_VIRT_BASE 0x00000000
#define SMDK2410_FLASH_PHYS_BASE 0x00000000
#define SMDK2410_FLASH_VIRT_BASE 0x80000000
内存从0x30000000开始的
ttb_base=0x30004000是translation table base,虚拟地址到实地址内存映射表的基地址
第177行,ttb_base要存放在cp15的reg2中
第196行,对section的进入权限控制,存放在cp15的reg3中
142 #define X_ARM_MMU_SECTION(abase,vbase,size,cache,buff,access) \
143 { int i; int j = abase; int k = vbase; \
144 for (i = size; i > 0 ; i--,j++,k++) \
145 { \
146 ARM_MMU_SECTION(ttb_base, j, k, cache, buff, access); \
147 } \
148 }
125 #define ARM_MMU_SECTION(ttb_base, actual_base, virtual_base, \
126 cacheable, bufferable, perm) \
127 CYG_MACRO_START \
128 register union ARM_MMU_FIRST_LEVEL_DESCRIPTOR desc; \
129 \
130 desc.word = 0; \
131 desc.section.id = ARM_MMU_FIRST_LEVEL_SECTION_ID; \
132 desc.section.imp = 1; \
133 desc.section.domain = 0; \
134 desc.section.c = (cacheable); \
135 desc.section.b = (bufferable); \
136 desc.section.ap = (perm); \
137 desc.section.base_address = (actual_base); \
138 *ARM_MMU_FIRST_LEVEL_DESCRIPTOR_ADDRESS(ttb_base, (virtual_base)) \
139 = desc.word; \
140 CYG_MACRO_END
将空间划分为以section为单位,即1M每个。
开始填充每个descriptor,按照手册上的位图填好就完事。
120 #define ARM_MMU_FIRST_LEVEL_DESCRIPTOR_ADDRESS(ttb_base, table_index) \
121 (unsigned long *)((unsigned long)(ttb_base) + ((table_index) << 2))
struct ARM_MMU_FIRST_LEVEL_SECTION {
int id : 2;
int b : 1;
int c : 1;
int imp : 1;
int domain : 4;
int sbz0 : 1;
int ap : 2;
int sbz1 : 8;
int base_address : 12;
};
为了有个直观的影响,现在把填好的ttb这个表列出来
address | b_addr:12 | sbz1:1 | ap:2 | sbz0:1 | domain:4 | imp:1 | c:1 | b:1 | id:2 |
0x30004000 | 0x300 | 0 | 3 | 0 | 0 | 1 | 1 | 1 | 2 |
… | … | 0 | 3 | 0 | 0 | 1 | 1 | 1 | 2 |
0x300040fc | 0x33f | 0 | 3 | 0 | 0 | 1 | 1 | 1 | 2 |
| | | | | | | | | |
0x30004c00 | 0x300 | 0 | 3 | 0 | 0 | 1 | 0 | 0 | 2 |
… | … | 0 | 3 | 0 | 0 | 1 | 0 | 0 | 2 |
0x30004cfc | 0x33f | 0 | 3 | 0 | 0 | 1 | 0 | 0 | 2 |
| | | | | | | | | |
0x30005000 | 0x400 | 0 | 3 | 0 | 0 | 1 | 1 | 1 | 2 |
| | | | | | | | | |
0x30005200 | 0x480 | 0 | 3 | 0 | 0 | 1 | 0 | 0 | 2 |
… | … | 0 | 3 | 0 | 0 | 1 | 0 | 0 | 2 |
0x300059fc | 0x67f | 0 | 3 | 0 | 0 | 1 | 0 | 0 | 2 |
| | | | | | | | | |
0x30006000 | 0x000 | 0 | 3 | 0 | 0 | 1 | 0 | 0 | 2 |
0x30006004 | 0x001 | 0 | 3 | 0 | 0 | 1 | 0 | 0 | 2 |
| | | | | | | | | |
< hal/arm/arch/v3_0/src/vectors.S >
464 // Call platform specific hardware initialization
465 bl hal_hardware_init
494 // Run through static constructors
495 bl cyg_hal_invoke_constructors
499 // This starts up the eCos kernel
500 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
501 ldr r1,=__startup_stack
502 mov sp,r1
503 #endif
504 bl cyg_start
第465行
<hal/arm/arm9/var/v3_0/src/arm9_misc.c>
67 void hal_hardware_init(void)
68 {
69 // Perform any platform specific initializations
70 plf_hardware_init();
72 // Set up eCos/ROM interfaces
73 hal_if_init();
75 #ifndef CYG_HAL_STARTUP_RAM
76 // Invalidate caches
77 HAL_DCACHE_INVALIDATE_ALL();
78 HAL_ICACHE_INVALIDATE_ALL();
79 #endif
80 // Enable caches
81 #ifdef CYGSEM_HAL_ENABLE_DCACHE_ON_STARTUP
82 HAL_DCACHE_ENABLE();
83 #endif
84 #ifdef CYGSEM_HAL_ENABLE_ICACHE_ON_STARTUP
85 HAL_ICACHE_ENABLE();
86 #endif
87 }
第70行
306 void
307 plf_hardware_init(void)
308 {
309 HAL_WRITE_UINT32(INTMOD, 0x0); //All=IRQ mode
310 HAL_WRITE_UINT32(INTMSK, BIT_ALLMSK); //All interrupt is masked.
311 HAL_WRITE_UINT32(INTSUBMSK, BIT_SUB_ALLMSK); //All sub-interrupt is masked.
313 port_init();
315 // Initialize real-time clock (for delays, etc, even if kernel doesn't use it)
316 hal_clock_initialize(CYGNUM_HAL_RTC_PERIOD);
317 }
第313行,设置gpio
第316行,设置时钟
第73行
hal_if_init()
:: hal_virtual_vector_table[]初始化为空操作
hal_virtual_vector_table[]是个全局的系统调用列表,每个的具体功能如下
// Main calling interface table. Will be assigned a location by the
// linker script. Both ROM and RAM startup applications will know about
// the location.
#define CYGNUM_CALL_IF_VERSION 0
#define CYGNUM_CALL_IF_available_1 1
#define CYGNUM_CALL_IF_available_2 2
#define CYGNUM_CALL_IF_available_3 3
#define CYGNUM_CALL_IF_KILL_VECTOR 4
#define CYGNUM_CALL_IF_CONSOLE_PROCS 5
#define CYGNUM_CALL_IF_DEBUG_PROCS 6
#define CYGNUM_CALL_IF_available_7 7
#define CYGNUM_CALL_IF_available_8 8
#define CYGNUM_CALL_IF_available_9 9
#define CYGNUM_CALL_IF_available_10 10
#define CYGNUM_CALL_IF_available_11 11
#define CYGNUM_CALL_IF_SET_DEBUG_COMM 12
#define CYGNUM_CALL_IF_SET_CONSOLE_COMM 13
#define CYGNUM_CALL_IF_MONITOR_VERSION 14
#define CYGNUM_CALL_IF_DBG_SYSCALL 15
#define CYGNUM_CALL_IF_RESET 16
#define CYGNUM_CALL_IF_CONSOLE_INTERRUPT_FLAG 17
#define CYGNUM_CALL_IF_DELAY_US 18
#define CYGNUM_CALL_IF_DBG_DATA 19
#define CYGNUM_CALL_IF_FLASH_CFG_OP 20
#define CYGNUM_CALL_IF_MONITOR_RETURN 21
#define CYGNUM_CALL_IF_FLASH_FIS_OP 22
#define CYGNUM_CALL_IF_FLASH_FIS_OP2 23
#define CYGNUM_CALL_IF_LAST_ENTRY CYGNUM_CALL_IF_FLASH_FIS_OP2
#define CYGNUM_CALL_IF_INSTALL_BPT_FN 35
#define CYGNUM_CALL_IF_TABLE_SIZE 64
:: 初始化该数组的每个成员
è cyg_hal_plf_comms_init()
è cyg_hal_plf_serial_init()
:: initiate serial and call CYGNUM_CALL_IF_SET_CONSOLE_COMM set console
è cyg_hal_plf_serial_init_channel()
:: initiate the serial channel
:: 此后串口应该设置好了,可以进行输出
hal_hardware_init()
è plf_hardware_init()
è hal_if_init()
è HAL_DCACHE_INVALIDATE_ALL()
:: dcache invalidate
è HAL_ICACHE_INVALIDATE_ALL()
:: icache invalidate
è HAL_DCACHE_ENABLE()
:: dcache enable
è HAL_ICACHE_ENABLE()
:: icache enable
cyg_hal_invoke_constructors()
:: 运行指令segment内的函数,但是没有找到相应的宏定义
然后,sp指向__startup_stack
跳转到cyg_start()运行
原文见:http://blog.sina.com.cn/s/blog_559f6ffc0100mjlq.html