• 013:ADS semihosting与硬件重定向(转)


    转自:http://www.linuxidc.com/Linux/2011-09/42019.htm

    应用程序在执行过程中经常会和主机有IO交互请求,例如C程序中的printf,该系统函数被执行时,会通过软件中断将printf请求提交给操作系统内核,内核将printf要打印的数据拷贝到内核空间,通过调用显示器驱动程序接口,将数据显示到显示器上。如下图所示:

     

    图3-10本地主机IO请求示意图

    上述应用程序IO请求是最常见的一种本地主机请求方式,在嵌入式系统开发过程中还存在一种半主机请求模式semihosting。

    1   semihosting半主机调试

    Semihosting技术将应用程序中的IO请求通过一定的通道传送到主机(host),由主机上的资源响应应用程序的IO请求,而不是像在主机上执行本地应用程序一样,由应用程序所在的计算机响应应用程序IO请求,也就是将目标板的输入/ 输出请求从应用程序代码传递到远程运行调试器的主机的一种机制。简单来说,目标开发板上通常不会有输入/输出这些外设,开发板运行的代码想要将结果打印出来,或者获得用户的输入,可以通过请求远程主机IO设备来实现,如:显示器,键盘等。目标开发板执行代码中加入对输入/输出设备进行访问函数,如:printf,scanf等,这些函数并不是目标开发板的库函数,而是远程主机交叉编译器中带有的库函数,这些库函数被编译时,编译成一条软件中断指令。当目标开发板上电运行之后,执行到请求访问输入/输出设备指令时,产生特定中断号的软件中断SWI(软件中断SWI指令请3.5系统调用与软件中断SWI的实现章节),与开发板相连的调试器会先截获目标板SWI请求,由于开发板程序中也可能存在用户自定义软件中断,为了区分二者,调试器会根据SWI的软中断号来判断是不是semihosting模式IO请求,如果是,则取出R0寄存器里代表的具体请求号,然后使用远程主机来响应目标板具体IO请求,而不是开发板本身去处理setmihosting请求。

    代表Semihosting模式软中断号:

    l 0x123456(ARM模式)
    l 0xab(Thumb模式)

    具体semihosting请求,通过寄存器R0里的值决定。

    semihosting 仅仅是一种调试手段,它的工作原理就是利用调试器捕捉目标环境运行过程中产生的值为0x123456的SWI中断,然后向远程主机调试环境发送对应的调试信息。也就是说目标开发板通过特定的软件中断指令,借用了远程主机的输入输出设备实现IO请求的访问。如下图所示。对于脱离调试环境开发板上运行的应用代码来说,是没有该机制的,也就是说是nonsemihost类型IO请求。

    图3-11 Semihosting远程主机IO请求(一)

     

    图3-12 Semihosting远程主机IO请求(二)

    Semihosting实验

    Semihosting控制LED灯实验

    initstkhp.s:堆栈初始化函数

     1          AREA initstkhp, CODE, READONLY
     2 
     3          EXPORT __user_initial_stackheap          ; 导出__user_initial_stackheap符号
     4 
     5 __user_initial_stackheap                                               ; 堆栈设置入口函数
     6 
     7          LDR r0, =0x31000000                                      ; 堆地址为0x31000000
     8          LDR r1, =0x33000000                                      ; 栈地址为0x33000000
     9          mov PC, LR
    10 
    11          END

    main.c:

    本程序首先初始化LED控制寄存器,使用标准C库里的printf,scanf分别在AXD终端窗口打印信息和获得用户键盘输入,根据用户输入数字,点亮对应的LED灯。

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 #define       GPBCON           (*(volatile unsigned long *)0x56000010)
     5 #define       GPBDAT           (*(volatile unsigned long *)0x56000014)
     6 #define       LEDS             (1<<5|1<<6|1<<7|1<<8)
     7 
     8 int main()
     9 {
    10 int i;
    11 
    12     GPBCON     = 0x00015400;
    13 
    14     while (1)
    15 
    16     {
    17         printf("please input led number: ");
    18         scanf("%d", &i);                                                             // 取得用户输入
    19         
    20 
    21         switch (i)
    22         {
    23             case 1:                                                                    // 输入1,点亮Led1
    24                  GPBDAT=(GPBDAT&(~LEDS)) | (1<<6|1<<7|1<<8);
    25                  printf("led1 on/n");
    26                  break;
    27 
    28             case 2:                                                                    // 输入2,点亮Led2
    29                  GPBDAT=(GPBDAT&(~LEDS)) | (1<<5|1<<7|1<<8);
    30                  printf("led2 on/n");
    31                  break;
    32 
    33             case 3:                                                                    // 输入3,点亮Led3
    34                  GPBDAT=(GPBDAT&(~LEDS)) | (1<<5|1<<6|1<<8);
    35                  printf("led3 on/n");
    36                  break;
    37 
    38             case 4:                                                                    // 输入4,点亮Led4
    39                  GPBDAT=(GPBDAT&(~LEDS)) | (1<<5|1<<6|1<<7);
    40                  printf("led4 on/n");
    41                  break;
    42 
    43             default:
    44                  printf("input error, please input 1 to 4/n");
    45                  break;
    46 
    47             }
    48       }
    49 }
    50 
    51  

    总结:

    Semihosting半主机调试模式,只能使用在开发板和调试主机通过仿真器连接的情况下,也就是说脱离了主机调试环境上述代码不能正常运行。目标开发板上执行的IO实际上是交给了远程主机来处理实现,正是因为如此,这种方式只适合在调试模式下,真正的嵌入式系统不可能依赖于主机实现IO处理的,嵌入式系统要想独立出来实现IO请求的处理,这就需要将输入输出库函数的底层相关硬件实现重定向。

  • 相关阅读:
    makefile 中 $@ $^ %< 使用
    makefile中的自动化变量$@,$%,$
    linux grep命令
    wc命令
    linux下echo命令
    winscp和putty提取固件教程
    WinSCP和PuTTY在刷openwrt固件的使用教程
    OPENWRT学习笔记入门篇
    第五章 并发性:互斥和同步
    getCurrentSession()和getOpenSession()的区别
  • 原文地址:https://www.cnblogs.com/afeibfp/p/2857845.html
Copyright © 2020-2023  润新知