16. 17. 18. 19. 20. 21. 22. 23. 24.
le */
25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38.
n) */
39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56.
13 uint32 n;
14 /* Declare pointers for various data sections. These pointers 15 * are initialized using values pulled in from the linker file 16 */
17 uint8 * data_ram, * data_rom, * data_rom_end; 18 uint8 * bss_start, * bss_end;
19 /* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker fi 20 extern uint32 __VECTOR_TABLE[]; 21 extern uint32 __VECTOR_RAM[];
22 /* Copy the vector table to RAM */ 23 if (__VECTOR_RAM != __VECTOR_TABLE) 24 {
25 for (n = 0; n < 0x410; n++)
26 __VECTOR_RAM[n] = __VECTOR_TABLE[n]; 27 }
28 /* Point the VTOR to the new copy of the vector table */ 29 write_vtor((uint32)__VECTOR_RAM);
30 /* Get the addresses for the .data section (initialized data sectio 31 data_ram = __section_begin(\); 32 data_rom = __section_begin(\); 33 data_rom_end = __section_end(\); 34 n = data_rom_end - data_rom;
35 /* Copy initialized data from ROM to RAM */ 36 while (n--)
37 *data_ram++ = *data_rom++;
38 /* Get the addresses for the .bss section (zero-initialized data) */ 39 bss_start = __section_begin(\); 40 bss_end = __section_end(\);
41 /* Clear the zero-initialized data section */ 42 n = bss_end - bss_start; 43 while(n--) 44 *bss_start++ = 0;
57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71.
45 /* Get addresses for any code sections that need to be copied from 46 * The IAR tools have a predefined keyword that can be used to mark 47 * functions for execution from RAM. Add \ before the retur 48 * the function prototype for any routines you need to execute from R 49 * of ROM. ex: __ramfunc void foo(void); 50 */
51 uint8* code_relocate_ram = __section_begin(\); 52 uint8* code_relocate = __section_begin(\); 53 uint8* code_relocate_end = __section_end(\);
ROM to RAM. individual n type in AM instead
54 /* Copy functions from ROM to RAM */ 55 n = code_relocate_end - code_relocate; 56 while (n--)
57 *code_relocate_ram++ = *code_relocate++; 58 }
在IAR中, #pragma section=\ 用来在C语言中指定一个名称是
NAME的段,align指定对齐方式。指定的段可以被段操作符来引用,段操作符包括 __section_begin, __section_end, 和 __section_size. 个人理
解.date、.date_init和.bss应该是IAR中保留的段名称,.date代表数据段中的常量,.date_init代表数据段中已初始化的变量,.bss代表未初始化的变量(zero)。
上面代码中,先是指定了5个不同名称的段(前3个是保留段名称,代表这些段是从这里开始的),CodeRelocate和CodeRelocateRam是在*.icf文件中定义的块(block): define block CodeRelocate { section .textrw_init }; define block CodeRelocateRam { section .textrw }; quote:
The __ramfunc keyword makes a function execute in RAM. Two code
sections will be created: one for the RAM execution (.textrw), and one for the ROM initialization (.textrw_init).
外部变量引用
extern uint32 __VECTOR_TABLE[]; extern uint32 __VECTOR_RAM[]; 来自IAR的链接文件(.icf),在.icf文件中已经定义了变量
__VECTOR_TABLE 和 __VECTOR_RAM 其值都是0x1fff0000.\RAM\这段代码进行判断,如果向量表不在RAM中,则把向量表拷贝到RAM开始的地址上,这里由于在RAM中调试,代码是直接下载到RAM中的,所以不用拷贝。
向量表已经在RAM中了,接下来要重定向向量表,以便在发生异常时到RAM中取得异常入口地址(默认情况下是在0x0取)。 write_vtor((uint32)__VECTOR_RAM) 这个函数用来写向量表偏移寄存器(VTOR,地址0xE000_ED08),这里写入的是RAM起始地址0x1FFF0000。注意这个地址是有要求的,并不是所有地址都能作为向量表起始地址,0x1FFF0000满足要求(这个要求就是:必须先求出系统中共有多少个向量,再把这个数字向上增大到是 2 的整次幂,而起始地址必须对齐到后者的边界上。例如,如果一共有 32 个中断,则共有 32+16(系统异常)=48个向量,向上增大到 2的整次幂后值为 64,因此地址地址必须能被 64*4=256整除,从而合法的起始地址可以是:0x0,0x100,0x200 等----参见ARM Contex-M3权威指南)。另外,如果向量表在RAM区(相对于code区),需把bit[29]置位,这里0x1FFF0000也满足要求。
后面的代码是拷贝数据到RAM中,搭建好C语言运行环境。
③sysinit()函数
上次写了飞思卡尔官方给出的demo程序的启动流程的前面部分:
在存储器最前面放置好向量表-->把通用寄存器清零-->开中断-->跳转到start函数继续执行初始化。在start函数中,顺次执行三个函数:禁用看门狗-->初始化C语言环境(向量表重定向、拷贝数据段到RAM、清零bss段等)-->系统外设初始化。
③系统外设初始化函数 sysinit() 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
#include \ #include \ #include \
/********************************************************************/
/* Actual system clock frequency */ int core_clk_khz; int core_clk_mhz; int periph_clk_khz;
/********************************************************************/
13. 14. 15. 16.
igure
void sysinit (void) {
/*
* Enable all of the port clocks. These have to be enabled to conf * pin muxing options, so most code will need all of these on anyw */
SIM_SCGC5 |= (SIM_SCGC5_PORTA_MASK | SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTE_MASK );
17.
ay.
18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29.
iables
/* Ramp up the system clock */
core_clk_mhz = pll_init(CORE_CLK_MHZ, REF_CLK);
/*
* Use the value obtained from the pll_init function to define var * for the core clock in kHz and also the peripheral clock. These * variables can be used by other functions that need awareness of the * system frequency. */
core_clk_khz = core_clk_mhz * 1000;
periph_clk_khz = core_clk_khz / (((SIM_CLKDIV1 & SIM_CLKDIV1_OUTDIV2_
30. 31. 32. 33. 34. 35. 36. 37.
at
MASK) >> 24)+ 1);
/* For debugging purposes, enable the trace clock and/or FB_CLK so th * we'll be able to monitor clocks and know the PLL is at the freque * that we expect. */
trace_clk_init(); fb_clk_init();
38.
ncy
39. 40. 41. 42. 43. 44. 45. 46. 47. 48.
is pin
/* Enable the pins for the selected UART */ if (TERM_PORT == UART0_BASE_PTR) {
/* Enable the UART0_TXD function on PTD6 */
PORTD_PCR6 = PORT_PCR_MUX(0x3); // UART is alt3 function for th
49.
50. 51.
is pin
/* Enable the UART0_RXD function on PTD7 */
PORTD_PCR7 = PORT_PCR_MUX(0x3); // UART is alt3 function for th }
52. 53. 54. 55. 56. 57.
if (TERM_PORT == UART1_BASE_PTR) {
/* Enable the UART1_TXD function on PTC4 */
PORTC_PCR4 = PORT_PCR_MUX(0x3); // UART is alt3 function for this
pin
58.
59. 60.
PORTC_PCR3 pin
61. 62.
63. 64. 65. 66.
PORTD_PCR3 pin
67.
68. 69.
PORTD_PCR2 pin
70. 71.
72. 73. 74. 75.
PORTC_PCR17 s pin
76.
77. 78.
PORTC_PCR16 s pin
79. 80. 81. 82. 83.
PORTE_PCR24 s pin
84.
85.
/* Enable the UART1_RXD function on PTC3 */
= PORT_PCR_MUX(0x3); // UART is alt3 function for this}
if (TERM_PORT == UART2_BASE_PTR) {
/* Enable the UART2_TXD function on PTD3 */
= PORT_PCR_MUX(0x3); // UART is alt3 function for this
/* Enable the UART2_RXD function on PTD2 */
= PORT_PCR_MUX(0x3); // UART is alt3 function for this}
if (TERM_PORT == UART3_BASE_PTR) {
/* Enable the UART3_TXD function on PTC17 */
= PORT_PCR_MUX(0x3); // UART is alt3 function for thi
/* Enable the UART3_RXD function on PTC16 */
= PORT_PCR_MUX(0x3); // UART is alt3 function for thi}
if (TERM_PORT == UART4_BASE_PTR) {
/* Enable the UART3_TXD function on PTC17 */
= PORT_PCR_MUX(0x3); // UART is alt3 function for thi
/* Enable the UART3_RXD function on PTC16 */