2009年10月7日 星期三

keil 對 Stack 的管理及local variable

最近...為了更一步了解其microc/os-II
回頭重看一下,關於相關的stack資訊
1.對於8051/52 memory map

記憶體種類

tab.1
type
SDCC
instruction
size
addressing
(A) program
__code
MOVC
64K
index direct
(B) external
__xdata
MOVX
64K
indirect
(C) internal(80~FF)
__idata
MOV
128
indirect
(C) SFR(80~FF)
__sfr
MOV
128
direct
(C) internal(0~7F)
__data
MOV
128
direct/indirect

記憶體定址

tab.2


type
read
write
register
direct
MOV Rn,direct
MOV direct,direct
MOV direct,Rn
MOV direct,@DPTR
MOV direct,#data
R0~R7,A
indirect
MOV direct,@Ri
MOVX A,@DPTR
MOV @Ri,direct
MOVX @DPTR,A
MOV @Ri,#data
R0,R1,DPTR,A
index direct
MOV A,#30h
MOV DPTR,#300H
MOVC A,@A+DPTR
X
A,DPTR
  1. Ri=R0,R1,Rn=R0~R7。
  2. 索引定址法 (index direct) 只能用在程式記憶體,而且不能寫入,只能讀取到 A。
  3. 外部記憶體只能使用間接定址法 (indirect),而且只能透過 Ri/DPTR/A 三者傳遞數值,如果要寫入數值,只能把值先存入 A,再由 A 寫入 DPTR/Ri。
  4. 內部記憶體不論間接或直接都可以直接把數值寫入,不需要透過 A,當然要經由 A 也是可以。

pic.1

pic.2


2.關於keil C 管理Stack

因為8051/52的RAM有限.故與一般的C對stack管理方式不同
  1. 對於keil C中,其對於local variable(區域變數)管理
  • 會依不同的設定,會對其local variable有不同的處理,C語言在對local variable會在其scope中對stack中allocated,但同樣地這樣做可能超過51的限制(51的stack是在idata(*1)。所以 compiler會自動作function間的dependency checking(*2,採用共用變數的方式,將local variable放在 _DATA_GROUP_。
  • Compiler的選項:Small,Compact,Large的設置就是決定這個segment存放的記憶體位置。
  • Small : variable in DATA,會將所有local variable放在 DATA,segment name叫_DATA_GROUP.
  • Compact : variable in PDATA,會將所有local variable放在PDATA,segment name叫_PDATA_GROUP_.
  • Large : variable in XDATA,會將所有local variable放在XDATA,segment name叫_XDATA_GROUP_.
2.


  • Optimize Level



  • 51 雖然有一般用途的stack和stack pointer,但是Keil C51並沒有真的像標準的C compiler一樣,將function local variable 放在stack中,反而是將local variable都自行allocate在RAM中固定位置,另外利用Compiler作function dependency tree。決定function間共用variable的時機。
  • 這要enable optimize : 2 - Data Overlaying,才會啟動。否則Keil C不會check function dependency而共用local variable。
  • 所以enable optimize 2以上,對RAM用量影響很大。
  • 另 外一個影響RAM用量的optimize的level是 4 : register variable。會在容許的時候,使用register作為local variable。這樣也可以節省ram的使用。但是register 的local variable在debug時無法顯示出來。必須要自己去找出register才行。
-----------------------------------------------------------------------
上面是keil c對於stack介紹及設定
接下來是對於不同的data,idata,pdata,xdata的介紹
3.
  • data,idata,xdata........可參考tab.1
  • 其data 為internal register;
  • idata也為internal ,但只能indirect access


  • type
    SDCC
    instruction
    size
    addressing
    (A) program
    __code
    MOVC
    64K
    index direct
    (B) external
    __xdata
    MOVX
    64K
    indirect
    (C) internal(80~FF)
    __idata
    MOV
    128
    indirect
    (C) SFR(80~FF)
    __sfr
    MOV
    128
    direct
    (C) internal(0~7F)
    __data
    MOV
    128
    direct/indirect


  • 而對於pdata---------
  • keil c對它的定義為-----Paged (256 bytes) external data memory; accessed by opcode MOVX @Rn.
  • 為indirect access ,且只能acess range 256 byte.
  • 見pic.2中的external data space上的F800---FFFF(在此有多個pdata
  • 256 Bytes On-chip RAM + 2048 Bytes addition XRAM.(PDATA
  • 在多數的device中,在存取其XRAM(0x0000~~0x00FF),並不需要額外設定(PPAGEENABLE ) 來對前XRAM 256存取;
  • allow PDATA access (MOVX @Rx)---就可以存取其XRAM(0x0000~~0x00FF)
  • Some devices have a special SFR that contains the upper address byte to use for PDATA accesses. Devices like the Infineon C517A have an SFR called XPAGE at address 0x91. In the startup code, you must set this SFR to the page number for PDATA. We recommend you use the first available memory page for the PDATA space (0xF8 in the case of the Infineon device).
  • 以下以w78516b為例




main.c
include

char xdata kk _at_ 0x0101;

void test(int a)
{
a=a;
}

void main()
{
char a[2];

char b;
test(1);
a[0]='a';
kk='c';
b='b';//test the add
for(;;)
;
}



 file : *.list

            ; FUNCTION _test (BEGIN)
                                           ; SOURCE LINE # 5
0000 7800        R     MOV     R0,#LOW a
0002 EE                MOV     A,R6
0003 F2                MOVX    @R0,A
0004 08                INC     R0
0005 EF                MOV     A,R7
0006 F2                MOVX    @R0,A
                                           ; SOURCE LINE # 6
                                           ; SOURCE LINE # 7
0007 7800        R     MOV     R0,#LOW a
0009 E2                MOVX    A,@R0
000A FE                MOV     R6,A
000B 08                INC     R0
000C E2                MOVX    A,@R0
000D FF                MOV     R7,A
000E 7800        R     MOV     R0,#LOW a
0010 EE                MOV     A,R6
0011 F2                MOVX    @R0,A
0012 08                INC     R0
0013 EF                MOV     A,R7
0014 F2                MOVX    @R0,A
                                           ; SOURCE LINE # 8
0015 22                RET    
             ; FUNCTION _test (END)

             ; FUNCTION main (BEGIN)
                                           ; SOURCE LINE # 10
                                           ; SOURCE LINE # 11
                                           ; SOURCE LINE # 15
0000 7F01              MOV     R7,#01H
0002 7E00              MOV     R6,#00H
0004 120000      R     LCALL   _test
                                           ; SOURCE LINE # 16
0007 7800        R     MOV     R0,#LOW a
0009 7461              MOV     A,#061H
000B F2                MOVX    @R0,A
                                           ; SOURCE LINE # 17
000C 900101            MOV     DPTR,#kk
000F 7463              MOV     A,#063H
0011 F0                MOVX    @DPTR,A
                                           ; SOURCE LINE # 18
0012 7800        R     MOV     R0,#LOW b
0014 7462              MOV     A,#062H
0016 F2                MOVX    @R0,A
                                           ; SOURCE LINE # 19
0017         ?C0002:
0017 80FE              SJMP    ?C0002
0019 22                RET    
             ; FUNCTION main (END)

其*.m51
LINK MAP OF MODULE: test (TEST)


TYPE BASE LENGTH RELOCATION SEGMENT NAME
-----------------------------------------------------

* * * * * * * D A T A M E M O R Y * * * * * * *
REG 0000H 0008H ABSOLUTE "REG BANK 0"
IDATA 0008H 0014H UNIT ?STACK

* * * * * * * X D A T A M E M O R Y * * * * * * *
XDATA 0000H 0005H INPAGE _PDATA_GROUP_
0005H 00FCH *** GAP ***
XDATA 0101H 0001H ABSOLUTE

* * * * * * * C O D E M E M O R Y * * * * * * *
CODE 0000H 0003H ABSOLUTE
CODE 0003H 0027H UNIT ?C_C51STARTUP
CODE 002AH 001AH UNIT ?PR?MAIN?TEST
CODE 0044H 0016H UNIT ?PR?_TEST?TEST

-------------------------------------------------------
*1.51的stack是在idata----並非一定在idata中,使用者也可宣告在它處

?C_C51STARTUP   SEGMENT   CODE
?STACK          SEGMENT   IDATA ;///在此是將?stack放在idata中

RSEG    ?STACK
DS      1       ;///可以加以決定出其最少空間給stack用
;DS     20      ;//最少保留10B
而在*.m51中
REG     0000H     0008H     ABSOLUTE     "REG BANK 0" ;work register
DATA    0008H     0005H     UNIT         _DATA_GROUP_ ;給local variable
IDATA   000DH     0014H     UNIT         ?STACK       ;最少保留空間 
2. 
如何設定其stack address
In the STARTUP code, change the following:
?STACK SEGMENT IDATA RSEG ?STACK DS 100h-080h
to:
ISEG AT 0xA0 ?STACK: DS 0x100 - ?STACK
This creates an absolute segment for the stack. Then, you can change the 0xA0 to the address where you want the stack to reside. This has the advantage that if your C program variables overlap with the stack, the linker emits a warning.
*2,dependency checking
為根據call-tree來決定其可overlay data
可以從其*.m51中得出.其餘下次再專論

沒有留言:

張貼留言