Chinaunix首页 | 论坛 | 博客
  • 博客访问: 51874
  • 博文数量: 18
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 172
  • 用 户 组: 普通用户
  • 注册时间: 2013-02-04 14:17
文章分类

全部博文(18)

文章存档

2014年(3)

2013年(15)

我的朋友

分类: LINUX

2013-10-29 10:51:09

来源:




1.CPU最简单的启动代码一般包括堆栈初始化,全局变量初始化,向量表初始化,
  最后跳转到用户主程序main执行;

2.cortex-m3的复位时序如下,
1),从地址0x00000000取出4bytes的数据作为MSP的值;
2),从地址0x00000004取出4bytes的数据作为复位的PC值;
3),PC跳到复位向量处开始往下执行程序代码。

3,用c代码编写启动代码。
cortex-m3规定好,从0x00000004存放系统异常,接下来就是IC的外部中断(具体布局跟不同厂商设计有关)。
由此我们可以定义个一维数组,按中断布局顺序对应存放不同的向量值。
下面是对应STM32中断布局定义的一维数组,相信有一点c基础的朋友很容易看懂。

typedef void (* const __ISR_FUNC)();       /*向量的数据类型,对应c编译器就是一个函数指针*/

__attribute__ ((section(".isr_vector")))   /*特别指定表格的section名称是isr_vector,连接器定位用到,下面第4点会介绍*/
__ISR_FUNC g_pfnVectors[] =
{
  (__ISR_FUNC)(&_eusrstack),     /*0x0000_0000 主堆栈的数组*/  
  Reset_Handler,           /*0x0000_0004 复位向量*/   
  NMI_Handler,             /*0x0000_0008*/
  HardFault_Handler,       /*0x0000_000C*/       
  MemManage_Handler,       /*0x0000_0010*/    
  BusFault_Handler,        /*0x0000_0014*/
  UsageFault_Handler,      /*0x0000_0018*/     
  (__ISR_FUNC)0,           /*0x0000_001C*/
  (__ISR_FUNC)0,           /*0x0000_0020*/
  (__ISR_FUNC)0,           /*0x0000_0024*/
  (__ISR_FUNC)0,           /*0x0000_0028*//* Reserved */
  SVC_Handler,             /*0x0000_002C*/
  DebugMon_Handler,        /*0x0000_0030*/
  (__ISR_FUNC)0,           /*0x0000_0034*/ /* Reserved */
  PendSV_Handler,          /*0x0000_0038*/
  SysTick_Handler,         /*0x0000_003C*/
  
  /*以上16个位系统异常*/
  
  /*下面的就是IC的外部中断(具体布局跟不同厂商设计有关)*/
  WWDG_IRQHandler,         /*0x0000_0040*/
  PVD_IRQHandler,
  TAMPER_IRQHandler,
  RTC_IRQHandler,
  FLASH_IRQHandler,
  RCC_IRQHandler,
  EXTI0_IRQHandler,
  EXTI1_IRQHandler,
  EXTI2_IRQHandler,
  EXTI3_IRQHandler,
  EXTI4_IRQHandler,
  DMA1_Channel1_IRQHandler,
  DMA1_Channel2_IRQHandler,
  DMA1_Channel3_IRQHandler,
  DMA1_Channel4_IRQHandler,
  DMA1_Channel5_IRQHandler,
  DMA1_Channel6_IRQHandler,
  DMA1_Channel7_IRQHandler,
  ADC1_2_IRQHandler,
  USB_HP_CAN_TX_IRQHandler,
  USB_LP_CAN_RX0_IRQHandler,
  CAN_RX1_IRQHandler,
  CAN_SCE_IRQHandler,
  EXTI9_5_IRQHandler,
  TIM1_BRK_IRQHandler,
  TIM1_UP_IRQHandler,
  TIM1_TRG_COM_IRQHandler,
  TIM1_CC_IRQHandler,
  TIM2_IRQHandler,
  TIM3_IRQHandler,
  TIM4_IRQHandler,
  I2C1_EV_IRQHandler,
  I2C1_ER_IRQHandler,
  I2C2_EV_IRQHandler,
  I2C2_ER_IRQHandler,
  SPI1_IRQHandler,
  SPI2_IRQHandler,
  USART1_IRQHandler,
  USART2_IRQHandler,
  USART3_IRQHandler,
  EXTI15_10_IRQHandler,
  RTCAlarm_IRQHandler,
  USBWakeUp_IRQHandler,
  (__ISR_FUNC)0,
  (__ISR_FUNC)0,
  (__ISR_FUNC)0,
  (__ISR_FUNC)0,
  (__ISR_FUNC)0,
  (__ISR_FUNC)0,
  (__ISR_FUNC)0,
  (__ISR_FUNC)0xF108F85F //this is a workaround for boot in RAM mode.
};

4.写好中断向量表的数据,如何在0x00000000起始处存放以上的数据表格呢?这就需要用到连接器ld来定位了,
接下来就简单介绍下如何定位中断向量表。

/*"以下是stm32的memery布局,flash是从0x80000000开始,其实0x80000000映射到0x00000000处的"*/
MEMORY
{
  RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K  /* also change _estack below */
  FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 512K
}

/*stm32的复位时向量表数据就放在0x80000000开始*/
SECTIONS
{
    .isr_vector :
    {
     . = ALIGN(4);           /*flash section内的定位符‘.’从0x80000000算起*/
        KEEP(*(.isr_vector)) /*把输入section isr_vector 放在0x80000000开始,就是我们的向量表格了*/
     . = ALIGN(4);
    } >FLASH
     
}

这里就不做多介绍ld的知识了,有兴趣的朋友可以研究以下,个人认为使用gccb编译器,会令你更深入了解c代码是如何生存的,如何对应指令集和内存的。
我只了解下皮毛,由于个人工作原因,没更多的时间深入研究学习。不过本人仍然保持这份兴趣。

5.以下再简单介绍下全都变量初始化,看下面代码:

void Reset_Handler(void)  /*这个常量函数指针就是放在0x0000_0004处的*/
{
    unsigned long *pulSrc, *pulDest;
    
    /***********************************************************************
    初始化有初始值的变量
    _sidata标识符就是初始化变量的rom镜像的起始地址,这是链接文件上定义的。
    _sdata标识符就是全局变量在ram中的起始地址,_edata标识符就是ram中的结束地址
    ************************************************************************/
    pulSrc = &_sidata;
    for(pulDest = &_sdata; pulDest < &_edata; )
    {
        *(pulDest++) = *(pulSrc++);
    }

    /*同理下面就是无初始值的变量,全清零*/
    for(pulDest = &_sbss; pulDest < &_ebss; )
    {
        *(pulDest++) = 0;
    }
    
    main();/*跳到用户主程序*/
}

以上就完成了简单的启动代码。写cortex的代码完全不用汇编代码,这得益于cortex复位启动时根据一个向量表来启动的。
有兴趣的可以研究学习下gun工具链,这对想搞liunx内核的非常有帮助。

阅读(1148) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~