• [转:hwwr112100] TinyOS startup.51详解


    在CC2530S上移植TinyOS,遇到的首个问题应当是存储器映射。如果从CC2430的基础上修改移植到CC2530,那么必定要考虑存储器的映射问题。

    图2-1为CC2530 XDATA存储空间。如果直接使用原startup.a51作为CC2530的启动文件,虽然程序可以运行,但是,不可避免的会出现错误,造成这些错误原因绝大多数是因为内存区域没有清零。下面给出两个已知的错误。

    问题1:移植CC2420(其实已经移植到了CC2520上,只是名字没有改)协议栈,当全部移植工作结束后,运行,会发现程序在AMQueueImplP.nc文件判断语句

     if (queue[clientId].msg != NULL) {

                return EBUSY;
            }

    总是为真,然后返回错误状态。值得注意的是queue这个数组属于全局变量,并且较大,而在startup.a51中并没有对XDATA存储区域进行清零,最终造成queue始终存在数据。

    问题2:为了使每个数据包带有唯一的包序列号,采用了软件生产随机数,实现代码在RandomMlcgP.nc中。程序运行后可以发现,第一个数据包的包序列号总是0x4E并不是0。

    解决方法:

        修改CC2430-F128.bat中XDATA的映射地址为(X:0x0001-X:0xFFFF),IDATA(I:0-I:0xFF)

        修改startup.a51中XDATALEN,改为XDATALEN        EQU     0x1000

    这样就保证了在启动代码执行完后,XDATA低0x1000单元被清零。

    下面给出从网上找到的关于startup.a51文件的详细解读:

    1.标号
    IDATALEN    EQU    80H    ; the length of IDATA memory in bytes.
    这里IDATALEN只是一个标号而已,和idata不是一回事!你要是愿意,这段程序里的
    IDATALEN你完全可以改成dog呀,pig呀,playboy呀这些标号(其实我的理想是过猪一
    样的生活,不愁吃喝,无忧无虑,可惜做不到),上面的这一句是说程序里面凡是用
    到IDATALEN的地方其实就是可以看成是80H这个数,你用80H去代替IDATALEN是完全对
    的。
    之所以取IDATALEN这么个名字,只是为了好记,表明和idata有一点点关系,不至于你
    的程序长了,假使你本来是用了playboy作为标号的,写到后来你就会忘了playboy到
    底是什么含义了。idata的范围是0~FFH。如果你想改成FFH,完全可以。
    2.清零
    IF IDATALEN <> 0
            MOV    R0,#IDATALEN - 1
            CLR    A
    IDATALOOP:    MOV    @R0,A
            DJNZ    R0,IDATALOOP
    关于这一段,很明显是在清零,如果上面idatalen=80H,那么是对0~7FH清零;如果
    你的程序是改写成:
    IDATALEN    EQU    0100H    ;
    就是对0~FFH清零。
    还要注意的是那条IF语句,下面再谈。
    二、如何按你意愿加载这段程序
    一般考虑到这个往往是你的设计中要区分上电复位和程序复位。有时候当程序复位时
    你不希望一些内存单元被清零了,那么你不对startup.a51作点修改,就不行了。
    默认是自动加载这段startup.a51的。
    所以你要这样做:
    把lib目录下的原始startup.a51文件拷到你的项目所在目录下,再把你项目目录下的
    这个startup.a51加入到你的项目中(在keil的集成环境中,希望你对这个是知道如何
    做的),然后对这个startup.a51加以修改。
    比如改成:
    IDATALEN    EQU    00H    ; the length of IDATA memory in bytes.
    然后编译链接。这样你的程序中就不会包含对idata清零的内码了。
    为什么?上面提到的IF语句的作用呀!当定义IDATALEN=0时,清零代码被跳过!

    Startup.a51的中文说明
    ;------------------------------------------------------------------------------
    ;  STARTUP.A51:   用户上电初始化程序
    ;------------------------------------------------------------------------------
    ;
    ;   用户定义需上电初始化的内存空间
    ;
    ;   使用以下EQU命令可定义在CPU复位时需用0进行初始化的内存空间
    ;
    ;;       ; IDATA 存储器的空间的绝对起始地址总是0.;
    IDATALEN   EQU   80H    ; 需用0进行初始化的IDATA存储器空间的字节数
    ;
    XDATASTART   EQU    0H    ; XDATA存储器空间的绝对起始地址
    XDATALEN   EQU    0H    ; 需用0进行初始化的XDATA存储器的空间字节数.
    ;
    PDATASTART   EQU    0H    ; PDATA存储器的空间的绝对起始地址
    PDATALEN   EQU    0H    ; 需用0进行初始化的PDATA存储器的空间字节数.
    ;
    ;   注意:    IDATA 存储器的空间在物理上包括了8051单片机的DATA和BIT存储器空间.
    ;            听 说 至少要保证与C51编译器运行库有关的存储器的空间进行0初始化 不知是否
    ;------------------------------------------------------------------------------
    ;
    ;   重入函数模拟初始化
    ;
    ;   以下用EQU指令定义了重入函数模拟堆栈指针的初始化
    ;
    ;   使用SMALL存储器模式时重入函数的堆栈空间 .
    IBPSTACK   EQU    0    ; 使用SMALL存储器模式重入函数时将其设置成1.
    IBPSTACKTOP   EQU    0FFH+1    ; 将堆栈顶设置为最高地址+1.
    ;
    ;   使用LARGE存储器模式时再入函数的堆栈空间.;   使用LARGE存储器模式时重入函数的堆栈空间. 
    XBPSTACK   EQU    0    ; 使用LARGE存储器模式再入函数时将其设置成1.
    XBPSTACKTOP   EQU    0FFFFH+1; 将堆栈顶设置为最高地址+1.
    ;
    ; 使用COMPACT存储器模式时再入函数的堆栈空间.; 使用COMPACT存储器模式时重入函数的堆栈空间. 
    PBPSTACK   EQU    0    ; 使用COMPACT存储器模式再入函数时将其设置成1.
    PBPSTACKTOP   EQU    0FFFFH+1; 将堆栈顶设置为最高地址+1.
    ;
    ;------------------------------------------------------------------------------
    ;
    ;   使用COMPACT存储器模式时64K字节XDATA存储器空间的分页定义
    ;
    ;   以下用EQU指令定义PDATA类型变量在XDATA存储器空间的页地址
    ;   使用EQU指令定义PFAGE时必须与L51连接定位器PDATA指令的控制参数一致
    ;
    PPAGEENABLE   EQU    0    ; 使用PDATA类型变量时将其设置成1.
    PPAGE      EQU    0    ; 定义页号.
    ;
    ;------------------------------------------------------------------------------
           NAME    ?C_STARTUP; 模块名为 ?C_STAUTUP
    ?C_C51STARTUP    SEGMENT    CODE       ; 代码
    ?STACK       SEGMENT    IDATA      ; 堆栈
           RSEG    ?STACK       ; 堆栈
          DS    1
           EXTRNEXTRN CODE   ((?C_START))    ; 程序开始地址
           PUBLIC    ?C_STARTUP
           CSEG    AT    0x8000   ;  定义用户程序的起始地址,用MON51仿真器时可能有用
    ?C_STARTUP:    LJMP    STARTUP1
           RSEG    ?C_C51STARTUP
    STARTUP1::
    ;
    ; 初始化串口
           MOV      SCON,#40H
           MOV    TMOD,#20H
           MOV    TH1,#0fdH
          SETB    TR1
          CLR    TI 
    ;   单片机上电IDATA内存清零 如果不需要上电清零IDATA 可以注销IF到IFEDN之间的话句
    ;   或者修改IDTALEN的长度 为了具有掉电保护功能 不知IDTALEN多长为好
    IF IDATALEN <> 0
           MOV    R0,#IDATALEN - 1
           CLR    A
    IDATALOOP:    MOV    @R0,A
           DJNZ    R0,IDATALOOP
    ENDIF
    ;
    ;   单片机上电XDATA内存清零 如果不需要上电清零XDATA 可以注销IF到IFEDN之间的话句
    ;   或者修改XDATALEN的长度
    IF XDATALEN <> 0
           MOV    DPTR,#XDATASTART
           MOV    R7,#LOW   ((XDATALEN)
       IF   (LOW   (XDATALEN) <> 0
           MOV    R6,#(HIGH   (XDATALEN) +1
       ELSE
           MOV    R6,,#HIGH ((XDATALEN)
       ENDIF
           CLR    A
    XDATALOOP:    MOVX    @DPTR,A
           INC    DPTR
           DJNZ    R7,XDATALOOP
           DJNZ    R6,XDATALOOP
    ENDIF
    ;
    ;   送PDATA存储器页面高位地址
    IF PAGEENABLE <> 0
           MOV    P2,#PPAGE
    ENDIF
    ;
    ;   单片机上电PDATA内存清零 如果不需要上电清零XDATA 可以注销IF到IFEDN之间的话句
    ;   或者修改PDATALEN的长度
    IF PDATALEN <> 0
           MOV    R0,#PDATASTART
           MOV    R7,#LOW   (PDATALEN)
           CLR    A
    PDATALOOP:    MOVX    @R0,A
           INC    R0
           DJNZ    R7,PDATALOOP
    ENDIF
    ;
    ;   设置使用SMALL存储器模式时再入函数的堆栈空间.
    IF IBPSTACK <> 0
    EXTRN DATA   (?C_IBP)
           MOV    ?C_IBP,#LOW IBPSTACKTOP
    ENDIF
    ;
    ;   设置使用LARGE存储器模式时再入函数的堆栈空间.
    IF XBPSTACK <> 0
    EXTRN DATA   (?C_XBP)
           MOV    ?C_XBP,#HIGH XBPSTACKTOP
           MOV    ?C_XBP+1,#LOW XBPSTACKTOP
    ENDIF
    ;
    ;   设置使用COMPACT存储器模式时再入函数的堆栈空间.
    IF PBPSTACK <> 0
    EXTRN DATA   (C_PBP)
           MOV    ?C_PBP,#LOW PBPSTACKTOP
    ENDIF
    ;
    ;   设置堆栈的起始地址
           MOV    SP,#?STACK-1    ; 例如 MOV   SP,#4FH;

    ; This code is required if you use L51_BANK.A51 with Banking Mode 4
    ; 如果你的程序使用了Mode 4 程序分组技术 请启动下面的程序,

    ; EXTRN CODE (?B_SWITCH0)
    ;                CALL     ?B_SWITCH0       ; init bank mechanism to code bank 0
    ;;                  程序从第一组bank 0 块开始执行
    ; 跳转到用户程序MAIN函数
           LJMP    ?C_START
          END
           ;lINSHENGFENG

    转自:http://blog.csdn.net/hwwr112100/article/details/6723796

    尊重原创

  • 相关阅读:
    Python超级篇-机器学习
    python高给篇-爬虫
    机器学习之-sklearn
    luogu3384 【模板】树链剖分
    bzoj3884 上帝与集合的正确用法
    luogu2765 魔术球问题
    poj2976 Dropping tests 01分数规划
    luogu2764 最小路径覆盖问题
    luogu2763 试题库问题
    luogu2762 太空飞行计划问题
  • 原文地址:https://www.cnblogs.com/dudu1990/p/2675106.html
Copyright © 2020-2023  润新知