12452|24

241

帖子

4

TA的资源

纯净的硅(初级)

楼主
 

Helper2416-24——YL-boot流程及部分源码解析(总结) [复制链接]

 
本帖最后由 yuanlai2010 于 2014-7-31 17:16 编辑

YL-boot流程及部分源码解析(总结)
参与Helper2416开发板助学计划心得
简介:
YL_boot本身就是一个裸机程序,也不算复杂,最近给它加入了启动内核的功能,终于也算得上是个真正的boot了。在后续的学习中,希望能移植一些高速数据传输的模块进去,让它变得更加完善。


YL-boot-for-SD 流程及代码解析
Note0
绿色的处理框代表是用汇编实现的,白色的使用C语言实现
Note1
通过串口传进来的文件(十六进制数据)的前56字节的数据先暂时存放在数组中,后续的数据库直接存放在物理地址0x30000038开始的位置,等数据全部传输完后,再把数组中的数据拷贝到0x30000000的位置,这是因为我需要用定时器来判断文件是否传输完毕,所以在物理地址0x30000000处的位置放置了异常向量表(通过MMU映射到0x00000000),文件接收完后就不需要中断功能了,所以可以直接覆盖这段位置的内容。
把数据放在这个位置是为了方便代码的运行,尤其是在开头放置了异常向量表的程序,由于开启MMU。所以用户代码可以直接从0x00000000处开始运行。
Note2
串口中文件的传输是连续的,字节与字节之间的时间间隔是一定的,每接收到一个字节就重装一次计数器的值,保证不会触发中断,当文件传输完后,不再重装计数器的值,就只能等着计数器的值减少到0,接着触发中断,来关闭这个接收字节的循环,完成文件的接收

Start.S解析
  1. @******************************************************************************
  2. @ File:Start.S
  3. @ 功能:启动文件
  4. @******************************************************************************
  5. @
  6.                 .set  IRQ_STACK_SIZE, 0x100
  7. @
  8. @ to set the mode bits in CPSR for different modes
  9. @
  10.                 .set  MODE_IRQ, 0x12
  11.                 .set  MODE_SVC, 0x13

  12.                 .equ  I_F_BIT, 0xC0

  13. .text
  14. .global Entry
  15. .global UserEntry
  16. Entry:
  17. @
  18. @ Stop Watchdog
  19. @
  20.                  LDR   R0, =0x53000000                                   @ Stop Watchdog
  21.                  MOV   R1, #0x00
  22.                  STR   R1, [R0]
  23. @
  24. @ Set up the Stack for IRQ mode
  25. @
  26.                  LDR   r0, =_stack                                           @ Read the stack address
  27.                  MSR   cpsr_c, #MODE_IRQ|I_F_BIT           @ change to IRQ mode
  28.                  MOV   sp,r0                                                   @ write the stack pointer
  29.                  SUB   r0,r0, #IRQ_STACK_SIZE                   @ give stack space
  30. @
  31. @ Set up the Stack for SVC mode
  32. @
  33.                  MSR   cpsr_c, #MODE_SVC|I_F_BIT           @ change to SVC mode
  34.                  MOV   sp,r0                                                   @ write the stack pointer
  35. @
  36. @ Clear the BSS section here
  37. @
  38. Clear_Bss_Section:

  39.                  LDR   r0, =_bss_start                                   @ Start address of BSS
  40.                  LDR   r1, =(_bss_end - 0x04)                   @ End address of BSS
  41.                  MOV   r2, #0
  42. Loop:
  43.                  STR   r2, [r0], #4                                    @ Clear one word in BSS
  44.                  CMP   r0, r1
  45.                  BLE   Loop                                                    @ Clear till BSS end


  46. @Lowlevel_init:
  47.                  BL                clock_init                                           @ Branch to clock_init

  48.                  BL                SDRAM_Init                                           @初始化sdram

  49.                  BL                mmu_init                                           @初始化并使能mmu

  50.                  BL                CopyVectorTable                                   @拷贝异常向量表到0x00000000

  51.                  BL                OriginalCopy                                   @跳转到OriginalCopy(main)函数

  52.                  @LDR         SP,        =0x04000000                                   @设置栈到04000000

  53.                  MOV    r1, #0                                                   @清除ICaches和DCaches中的数据
  54.                  MCR    p15, 0, r1, c7, c7, 0

  55.                  LDR        PC,        UserEntry                                   @跳转到SDRAM执行用户程序(0x00000000)

  56. UserEntry:
  57.                 .word        0x0

  58. .end
复制代码
Note0:
当程序从OriginalCopy返回后,需要使无效ICache中的数据,由于开启了MMU和Cache。在接收文件的时候使用了中断,CPU在中断处理的时候从0x00000000的中断向量表中读取了指令,会把这附近的指令全部读取到Cache中,如果没有使无效ICache就跳转到0x00000000执行用户代码的话,就会出现问题咯,因为CPU直接从Cache中读取数据了,这时候读取的就还是原来的中断向量表。所以需要使无效Cache中的数据,让CPU重新从0x00000000(物理地址0x30000000)处读取指令。

CopyVectorTable解析
  1. /***********************************************************************
  2. **                     EXTERNAL FUNCTION PROTOTYPES
  3. ***********************************************************************/
  4. extern void Entry(void);
  5. extern void UndefInstHandler(void);
  6. extern void SVC_Handler(void);
  7. extern void AbortHandler(void);
  8. extern void IRQHandler(void);
  9. extern void FIQHandler(void);

  10. /******************************************************************************
  11. **                      INTERNAL VARIABLE DEFINITIONS
  12. *******************************************************************************/
  13. const unsigned int S3C2416_VECTOR_BASE = 0x30000000;

  14. static unsigned int const vecTbl[14]=
  15. {
  16.     0xE59FF018,    /* Opcode for loading PC with the contents of [PC + 0x18] */
  17.     0xE59FF018,    /* Opcode for loading PC with the contents of [PC + 0x18] */
  18.     0xE59FF018,    /* Opcode for loading PC with the contents of [PC + 0x18] */
  19.     0xE59FF018,    /* Opcode for loading PC with the contents of [PC + 0x18] */
  20.     0xE59FF014,    /* Opcode for loading PC with the contents of [PC + 0x14] */
  21.     0xE59FF010,    /* Opcode for loading PC with (PC - 8)  (eq. to while(1)) */
  22.     0xE59FF010,    /* Opcode for loading PC with the contents of [PC + 0x10] */
  23.     0xE59FF010,    /* Opcode for loading PC with the contents of [PC + 0x10] */
  24.     (unsigned int)Entry,
  25.     (unsigned int)UndefInstHandler,
  26.     (unsigned int)SVC_Handler,
  27.     (unsigned int)AbortHandler,
  28.     (unsigned int)IRQHandler,
  29.     (unsigned int)FIQHandler
  30. };


  31. /******************************************************************************
  32. **                          FUNCTION DEFINITIONS
  33. *******************************************************************************/
  34. /**
  35. * \brief   This function copies the vector table to a location in OCMC
  36. *          RAM and sets the vector base address register.
  37. *
  38. * \param   None.
  39. *
  40. * \return  None.
  41. *
  42. **/
  43. void CopyVectorTable(void)
  44. {
  45.     unsigned int *dest = (unsigned int *)S3C2416_VECTOR_BASE;
  46.     unsigned int *src =  (unsigned int *)vecTbl;
  47.     unsigned int count;

  48.     for(count = 0; count < sizeof(vecTbl)/sizeof(vecTbl[0]); count++)
  49.     {
  50.         dest[count] = src[count];
  51.     }
  52. }

  53. /***************************** End Of File ***********************************/
复制代码
Note
由于从IROM启动,并不能直接使用中断向量表,同时要将64M的SDRA重映射到0x00000000处,所以也不同时能将0x40000000处内部SRAM重映射到0x00000000处,为了使用异常向量表,所以只能把异常向量表复制到SDRAM的开始的位置了,由于链接地址的关系,所以需要自己直接将机器码写到到数组中,然后在通过C函数复制到指定位置

OriginalCopy(主函数)解析
  1. /************************** include ****************************/
  2. #include "uart.h"
  3. #include "led_beep.h"
  4. #include "timer.h"
  5. #include "nand.h"
  6. #include "interruptcontrol.h"

  7. extern char flag;

  8. /************************** functions **************************/
  9. void OriginalCopy()
  10. {
  11.         volatile unsigned char tmpcode[60];
  12.         volatile unsigned char *codeaddr = (volatile unsigned char *)0x30000000;
  13.         unsigned int Length,cLength,dataddr = 0;
  14.         unsigned int i = 0;
  15.         char c,tmp;

  16.         uart_init();
  17.         LED_init();
  18.     BEEP_init();
  19.     delay(30000);
  20.     BEEP(0);
  21.         LED(1);
  22.     int_initialize();
  23.     int_register(1, 10, timer0_handler);
  24.     timer_init();

  25.     printuart(" ***** YL-boot  for SD ***** \r\n");
  26.     printuart("   EEWORLD ID: yuanlai2010  \r\n");
  27.     printuart(" *******  2014-07-30  ****** \r\n");
  28.     printuart(" Recieve file from UART ! \r\n");
  29.     printuart(" Please send your file \r\n");
  30.     printuart(" \r\n");
  31.         while(flag)
  32.         {
  33.                 if(i<56)
  34.                 {
  35.                         tmpcode[i++] = getchar();
  36.                         if(55==i)
  37.                         {
  38.                                 LED(0);
  39.                         }
  40.                 }
  41.                 else
  42.                 {
  43.                         reloadeTCNT0();
  44.                         codeaddr[i++] = getchar();
  45.                 }
  46.         }
  47.     int_disable();
  48.         Length = i;
  49.         for(i=0;i<56;i++)
  50.         {
  51.                 codeaddr[i] = tmpcode[i];
  52.         }
  53.         LED(1);
  54.     BEEP(1);
  55.     delay(30000);
  56.     BEEP(0);

  57.     printuart(" Recieve Successful ! \r\n");
  58.     printuart(" 1:Execute code in SDRAM  \r\n");
  59.     printuart(" 2:Flash file to NAND  \r\n");

  60.     flag = 1;
  61.         while(flag)
  62.         {
  63.                 c = getchar();
  64.         putchar(c);
  65.         printuart(" \r\n");
  66.         BEEP(1);
  67.         delay(30000);
  68.         BEEP(0);

  69.                 if('1'==c)
  70.                 {
  71.                         printuart(" Is to jump to your code !\r\n");
  72.             printuart(" **********  end  ********** \r\n\r\n");
  73.                         LED(0);
  74.                         delay(10000);
  75.                         return;
  76.                 }
  77.                 else if('2'==c)
  78.                 {
  79.                         printuart(" Where do you want to start ?\r\n");
  80.                         i = 0;
  81.                         while(1)
  82.                         {
  83.                                 tmpcode[i] = getchar();
  84.                                 if((tmpcode[i] == '\r') || (tmpcode[i] == '\n'))
  85.                                 {
  86.                                         cLength = i;
  87.                                         break;
  88.                                 }
  89.                                 putchar(tmpcode[i]);
  90.                                 i++;
  91.                         }
  92.                         for(i=2;i<cLength;i++)
  93.                         {
  94.                                 if((tmpcode[1] == 'x')||(tmpcode[1] == 'X'))
  95.                                 {
  96.                                         if(tmpcode[i] > 0x40)
  97.                                         {
  98.                                                 tmp = tmpcode[i] -0x31;
  99.                                         }
  100.                                         else
  101.                                         {
  102.                                                 tmp = tmpcode[i] -0x30;
  103.                                         }
  104.                                         dataddr <<= 4;
  105.                                         dataddr |= tmp;
  106.                                 }
  107.                         }
  108.                         printuart(" \r\n");
  109.             BEEP(1);
  110.             delay(30000);
  111.             BEEP(0);

  112.                         Nand_Init();
  113.                         if(0==Nand_WriteSkipBad(dataddr,
  114.                                                                         codeaddr,
  115.                                                                         Length))
  116.                         {
  117.                 BEEP(1);
  118.                 delay(30000);
  119.                 BEEP(0);
  120.                                 printuart(" Successful !\r\n");
  121.                 printuart(" **********  end  ********** \r\n\r\n");
  122.                         }
  123.                         else
  124.                         {
  125.                 BEEP(1);
  126.                 delay(30000);
  127.                 BEEP(0);
  128.                 printuart(" Fault !\r\n");
  129.                 printuart(" **********  end  ********** \r\n\r\n");
  130.                         }
  131.                         while(1);
  132.                 }
  133.         }
  134. }
  135. /**************************    end    **************************/
复制代码
Note
在接收烧写地址的时候,在PC上串口终端输入的是ASCII字符,而烧写地址是个unsigned int 类型的数据,所以需要有一个转换过程,为了能在一个函数中分析其原理,就不它写作一个单独的函数了。


YL-bioot-for_Kernel 流程及代码解析:
Note0
绿色的处理框代表是用汇编实现的,白色的使用C语言实现
Note1
相当于YL_boot_for_SD来说,这个流程很简单,各人认为这里最重要的就是设置好启动参数,以及怎么将参数传递给内核。

Original(主函数)解析
  1. /******************************** include ********************************/
  2. #include "nand.h"
  3. #include "uart.h"
  4. #include "boot_kernel.h"
  5. /****************************** functions ********************************/
  6. void original()
  7. {
  8.         volatile unsigned char *codeindex = (volatile unsigned char *)0x30008000;

  9.         uart_init();
  10.         Nand_Init();
  11.     printuart(" ******** YL-boot ******** \r\n");
  12.     printuart(" EEWORLD ID: yuanlai2010  \r\n");
  13.     printuart(" ******* 2014-07-29 ****** \r\n");
  14.     printuart(" \r\n");
  15.     printuart(" *****  Start Kernel  **** \r\n");
  16.         printuart(" Loading Kernel ...... \r\n");
  17.         if(0==Nand_ReadSkipBad(0x40000,
  18.                                                         codeindex,
  19.                                                         0x300000))
  20.         {
  21.                 printuart(" Jumping to Kernel \r\n");
  22.                 printuart(" ********** end ********** \r\n\r\n");
  23.                 do_bootm_linux();
  24.         }
  25.         else
  26.         {
  27.                 printuart(" Loarding Error \r\n");
  28.                 printuart(" ********** end ********** \r\n\r\n");
  29.         }
  30.         while(1);
  31. }
  32. /**************************** Code end ***********************************/
复制代码
Note
这里除了do_bootm_linux这个函数来说,都只是简单数据代码搬运的代码。关键在于do_bootm_linux这个函数,函数将完成设置启动参数及跳转至内核的工作,这个函数也是参照u-boot源码中do_bootm_linux函数来写的。

do_bootm_linux解析
do_bootm_linux.h
  1. #ifndef __BOOT_KERNEL_H
  2. #define __BOOT_KERNEL_H
  3. /**************************definition of symbols**************************/
  4. #define tag_next(t)        ((struct tag *)((unsigned int *)(t) + (t)->hdr.size))
  5. #define tag_size(type)        ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)

  6. typedef struct bd_info {
  7.     unsigned int                bi_arch_number;        /* unique id for this board */
  8.     unsigned int                bi_boot_params;        /* where this board expects params */
  9.     struct                                /* RAM configuration */
  10.     {
  11.         unsigned int start;
  12.         unsigned int size;
  13.     }                        bi_dram;
  14. }bd_t;

  15. /* The list ends with an ATAG_NONE node. */
  16. #define ATAG_NONE        0x00000000
  17. struct tag_header {
  18.         unsigned int size;
  19.         unsigned int tag;
  20. };

  21. /* The list must start with an ATAG_CORE node */
  22. #define ATAG_CORE        0x54410001
  23. struct tag_core {
  24.         unsigned int flags;                /* bit 0 = read-only */
  25.         unsigned int pagesize;
  26.         unsigned int rootdev;
  27. };

  28. #define ATAG_MEM        0x54410002
  29. struct tag_mem32 {
  30.         unsigned int        size;
  31.         unsigned int        start;        /* physical start address */
  32. };

  33. #define ATAG_INITRD        0x54410005
  34. /* describes where the compressed ramdisk image lives (physical address) */
  35. #define ATAG_INITRD2        0x54420005
  36. struct tag_initrd {
  37.         unsigned int start;        /* physical start address */
  38.         unsigned int size;        /* size of compressed ramdisk image in bytes */
  39. };

  40. /* command line: \0 terminated string */
  41. #define ATAG_CMDLINE        0x54410009
  42. struct tag_cmdline {
  43.         char        cmdline[1];        /* this is the minimum size */
  44. };

  45. struct tag {
  46.         struct tag_header hdr;
  47.         union {
  48.                 struct tag_core         core;
  49.                 struct tag_mem32        mem;
  50.                 struct tag_initrd       initrd;
  51.                 struct tag_cmdline      cmdline;
  52.         }u;
  53. };

  54. void do_bootm_linux(void);


  55. #endif
复制代码
do_bootm_linux.c
  1. /******************************** include ********************************/
  2. #include "boot_kernel.h"
  3. /******************************** functions *******************************/
  4. static struct tag *params;

  5. char *commandline = "root=/dev/mtdblock2 console=ttySAC0,115200 rootfstype=yaffs2 mem=64m";
  6. //root=/dev/mtdblock2 console=ttySAC0,115200 rootfstype=yaffs2 mem=64m
  7. unsigned int kernel_entry = 0x30008000;

  8. bd_t bd = {1685,0x30000100,{0x30000000,0x4000000}};

  9. unsigned int strlen(const char * s)
  10. {
  11.         const char *sc;

  12.         for (sc = s; *sc != '\0'; ++sc)
  13.                 /* nothing */;
  14.         return sc - s;
  15. }

  16. char * strcpy(char * dest,const char *src)
  17. {
  18.         char *tmp = dest;

  19.         while ((*dest++ = *src++) != '\0')
  20.                 /* nothing */;
  21.         return tmp;
  22. }

  23. static void setup_start_tag (bd_t bd)
  24. {
  25.         params = (struct tag *) bd.bi_boot_params;

  26.         params->hdr.tag = ATAG_CORE;
  27.         params->hdr.size = tag_size (tag_core);

  28.         params->u.core.flags = 0;
  29.         params->u.core.pagesize = 0;
  30.         params->u.core.rootdev = 0;

  31.         params = tag_next (params);
  32. }

  33. static void setup_memory_tags (bd_t bd)
  34. {
  35.         int i;

  36.         params->hdr.tag = ATAG_MEM;
  37.         params->hdr.size = tag_size (tag_mem32);

  38.         params->u.mem.start = bd.bi_dram.start;
  39.         params->u.mem.size = bd.bi_dram.size;

  40.         params = tag_next (params);
  41. }


  42. static void setup_commandline_tag (bd_t bd, char *commandline)
  43. {
  44.         char *p;

  45.         if (!commandline)
  46.                 return;

  47.         /* eat leading white space */
  48.         for (p = commandline; *p == ' '; p++);

  49.         /* skip non-existent command lines so the kernel will still
  50.          * use its default command line.
  51.          */
  52.         if (*p == '\0')
  53.                 return;

  54.         params->hdr.tag = ATAG_CMDLINE;
  55.         params->hdr.size =
  56.                 (sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;

  57.         strcpy (params->u.cmdline.cmdline, p);

  58.         params = tag_next (params);
  59. }

  60. static void setup_initrd_tag (bd_t bd, unsigned int initrd_start, unsigned int initrd_end)
  61. {
  62.         /* an ATAG_INITRD node tells the kernel where the compressed
  63.          * ramdisk can be found. ATAG_RDIMG is a better name, actually.
  64.          */
  65.         params->hdr.tag = ATAG_INITRD2;
  66.         params->hdr.size = tag_size (tag_initrd);

  67.         params->u.initrd.start = initrd_start;
  68.         params->u.initrd.size = initrd_end - initrd_start;

  69.         params = tag_next (params);
  70. }

  71. static void setup_end_tag (bd_t bd)
  72. {
  73.         params->hdr.tag = ATAG_NONE;
  74.         params->hdr.size = 0;
  75. }


  76. static void setup_tag(void)
  77. {
  78.         setup_start_tag (bd);
  79.         setup_memory_tags (bd);
  80.         setup_commandline_tag (bd, commandline);
  81.     setup_initrd_tag (bd, 0, 0);
  82.         setup_end_tag (bd);
  83. }

  84. void do_bootm_linux(void)
  85. {
  86.         int        machid = bd.bi_arch_number;
  87.         void        (*theKernel)(int zero, int arch, unsigned int params);
  88.         theKernel = (void (*)(int, int, unsigned int))kernel_entry;
  89.         setup_tag();
  90.         theKernel(0, machid, bd.bi_boot_params);
  91. }

  92. /**************************** Code end ***********************************/
复制代码
Note0
由于此boot是专门用于Helper2416开发板,所以所有的参数都是直接在程序中给定的,代码不会去检测硬件信息。
Note1
对于内核的启动只需要设置好memory_tags和commandline_tag这两个参数就好了,而start_tag和end_tag是必须的,对于initrd_tag不需要,因为Helper2416d的系统并没有用到RAMDISK,所以这里给它的后面两个参数都是0,也可以直接不要这个tag。memory_tags主要用于传递内存信息,commandline_tag指定了根文件系统的位置及指定了终端设备等信息
Note2
theKernel是一个函数指针,同时这个指针指向的就是zImage的最终存放位置。当执行这条函数的时候,就一去不复返了,此后的BOOT代码将不会在用到了,所有的权限就交给内核了


自编boot体会:
对于编写这个boot只是让学习的裸机编程有个可以应用的地方,同时通过编写这个boot让自己进一步了解了u-boot的工作原理,也锻炼了自己分析复杂源码的能力,为以后深入学习linux内核做好一些准备。同时也发现,再复杂的程序按照步骤一步一步来,总能分析清楚的,不要被复杂的代码所吓到!坚持下去,慢慢发现自己会有进步的!

YL-boot-for-SD源码:
游客,如果您要查看本帖隐藏内容请回复
YL-bioot-for_Kernel源码:
游客,如果您要查看本帖隐藏内容请回复

论坛ID:yuanlai2010
发表时间:2014-07-31



最新回复

学习了,谢谢  详情 回复 发表于 2023-3-18 20:14
点赞 关注

回复
举报

1461

帖子

1

TA的资源

纯净的硅(中级)

沙发
 
大神
 
 

回复

172

帖子

3

TA的资源

一粒金砂(中级)

板凳
 
没看完,顶楼主
 
 
 

回复

43

帖子

0

TA的资源

一粒金砂(中级)

4
 
来哥大神,,求带走。。
 
 
 

回复

2144

帖子

3

TA的资源

五彩晶圆(中级)

5
 
不错学习一下
打算裸奔玩玩
 
个人签名电工
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

6
 
下载下来研究一下,好资料
 
 
 

回复

267

帖子

0

TA的资源

一粒金砂(高级)

7
 
牛擦擦~~
 
个人签名

gitee/casy

 
 

回复

12

帖子

0

TA的资源

一粒金砂(中级)

8
 
都是大神
 
 
 

回复

18

帖子

0

TA的资源

一粒金砂(中级)

9
 
本帖最后由 desig 于 2014-9-4 17:51 编辑

很好的总结,学习来了,请问用那个工具编译呢

点评

这是在linux下用GCC编译的  详情 回复 发表于 2014-9-4 22:52
 
 
 

回复

554

帖子

0

TA的资源

版主

10
 
desig 发表于 2014-9-4 17:45
很好的总结,学习来了,请问用那个工具编译呢

这是在linux下用GCC编译的
 
个人签名My dreams will go on...
http://www.jyxtec.com
 
 

回复

18

帖子

0

TA的资源

一粒金砂(中级)

11
 
学习一下楼主的bootloader
 
 
 

回复

18

帖子

0

TA的资源

一粒金砂(中级)

12
 
本帖最后由 sdwuyawen 于 2014-9-18 10:44 编辑

根据楼主的思路,尝试了修改了一下向量表,把向量表放在text端开始处。向量表里是直接把ISR的地址赋给PC,代码如下:
  1. Entry:
  2. Vectors:       LDR                PC,Reset_Addr        
  3.                   LDR     PC,Undef_Addr
  4.                   LDR                PC,SWI_Addr
  5.                   LDR                PC,PAbt_Addr
  6.                   LDR     PC,DAbt_Addr
  7.                   B                AbortHandler
  8.                   LDR                PC,IRQ_Addr
  9.                   LDR                PC,FIQ_Addr

  10. Reset_Addr:       .word        Reset_Handler
  11. Undef_Addr:      .word        UndefInstHandler
  12. SWI_Addr:        .word        SVC_Handler
  13. PAbt_Addr:        .word        AbortHandler
  14. DAbt_Addr:        .word        AbortHandler
  15.                         
  16. IRQ_Addr:        .word        IRQHandler
  17. FIQ_Addr:        .word        FIQHandler
复制代码


就是在中断向量里,把ISR函数的绝对地址直接赋给PC,而不是采用PC相对地址的方式。上面的代码能实现这个功能,但是比较麻烦。有没有更简洁一些的方法把ISR函数的绝对地址赋给PC?希望大神指点一下。

同时修改了向量表copy函数,把text段开始的16x4个bytes拷贝到PA 0x30000000(映射到VA 0x00000000),也能正常使用。不知道有没有处理向量表的更好的方式?

  1. void CopyVectorTable(void)
  2. {
  3.     unsigned int *dest = (unsigned int *)S3C2416_VECTOR_BASE;
  4.     unsigned int *src =  (unsigned int *)0x40000000;
  5.     unsigned int count;
  6.     for(count = 0; count < 16; count++)
  7.     {
  8.         dest[count] = src[count];
  9.     }
  10. }
复制代码


还有一个小问题,楼主的打印字符串函数:
  1. void printuart(char *string)
  2. {
  3.     unsigned int i = 0;
  4.     while(string[i++] != '\0')
  5.     {
  6.         putchar(string[i]);
  7.     }
  8. }
复制代码


i++的位置好像有些问题,修改一下就正常了。
  1. void printuart(char *string)
  2. {
  3.     unsigned int i = 0;
  4.     while(string[i] != '\0')
  5.     {
  6.         putchar(string[i++]);
  7.     }
  8. }
复制代码

点评

异常向量变的位置是在0地址,代码是在0x40000000+(异常向量表的长度)的位置开始执行的…相对地址的话有个32M的跳转范围,这里显然是不够的,所以也只能使用绝对地址。 对于更好的向量处理方法我暂时还没想到  详情 回复 发表于 2014-9-18 11:44
 
 
 

回复

241

帖子

4

TA的资源

纯净的硅(初级)

13
 
sdwuyawen 发表于 2014-9-18 10:43
根据楼主的思路,尝试了修改了一下向量表,把向量表放在text端开始处。向量表里是直接把ISR的地址赋给PC, ...

异常向量变的位置是在0地址,代码是在0x40000000+(异常向量表的长度)的位置开始执行的…相对地址的话有个32M的跳转范围,这里显然是不够的,所以也只能使用绝对地址。

对于更好的向量处理方法我暂时还没想到

打印函数确实是个疏忽啊,调试的时候都没发现~~~

点评

好像跳转指令B的跳转范围是32MB,直接修改PC的寻址范围是4GB。能不能用一条指令完成修改PC并跳转?而不是这种方式?  详情 回复 发表于 2014-9-18 15:51
 
 
 

回复

18

帖子

0

TA的资源

一粒金砂(中级)

14
 
本帖最后由 sdwuyawen 于 2014-9-18 15:53 编辑
yuanlai2010 发表于 2014-9-18 11:44
异常向量变的位置是在0地址,代码是在0x40000000+(异常向量表的长度)的位置开始执行的…相对地址的话有个 ...

好像跳转指令B的跳转范围是32MB,直接修改PC的寻址范围是4GB。能不能用一条指令完成修改PC并跳转?而不是这种方式?
  1. LDR    PC,Reset_Addr
  2. Reset_Addr:       .word        Reset_Handler
复制代码




点评

这种就是使用绝对地址的方式完成的,如果是一条语句完成就是使用相对地址,使用B 或者 BL ,但是由于范围原因,B /BL都不本完成这项工作 ,所能只能用绝对地址的方式!  详情 回复 发表于 2014-9-18 16:08
 
 
 

回复

241

帖子

4

TA的资源

纯净的硅(初级)

15
 
sdwuyawen 发表于 2014-9-18 15:51
好像跳转指令B的跳转范围是32MB,直接修改PC的寻址范围是4GB。能不能用一条指令完成修改PC并跳转?而不是 ...

这种就是使用绝对地址的方式完成的,如果是一条语句完成就是使用相对地址,使用B 或者 BL ,但是由于范围原因,B /BL都不本完成这项工作 ,所能只能用绝对地址的方式!

 
 
 

回复

20

帖子

0

TA的资源

一粒金砂(中级)

16
 
认真学习
 
 
 

回复

37

帖子

0

TA的资源

一粒金砂(中级)

17
 
谢谢
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(中级)

18
 

 
 
 

回复

9

帖子

0

TA的资源

一粒金砂(初级)

19
 
学习啊啊
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

20
 
谢谢分享




 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表