📄 c519.txt
字号:
+_> ?PR?_EXECUTE?MAIN
?PR?FUNC1?MAIN 0025H 000BH
- -
?PR?FUNC2?MAIN 0025H 000BH
- -
?PR?FUNC3?MAIN 0025H 000BH
- -
?PR?_EXECUTE?MAIN 0025H 000EH
+_> ?C_LIB_CODE
D:0028H SYMBOL tex // Execute's variables
no longer
D:0029H SYMBOL arrex // overlaid with func4/
5's
D:0008H SYMBOL y
D:0009H SYMBOL arr4
D:0013H SYMBOL y5
D:0014H SYMBOL arr5
*** WARNING 16: UNCALLED SEGMENT,IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?FUNC4?MAIN
*** WARNING 16: UNCALLED SEGMENT,IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?FUNC5?MAIN
Note: The WARNING 16's show that func4/5 have been removed from the overlay
process to remove the hazard. See section 8.4.2.6 on the "UNCALLED SEGMENT,
IGNORED FOR OVERLAY
PROCESS" warning.
8.4.2.3 Function Jump Table Warning
(Non-hazardous)
Here two functions are called an array of function pointers. The array "jump
_table" exists in a segment called "?CO?MAIN1, i.e. the constant area assign
ed to module main. The problem arises that the two message string arguments
to the printf 's are also sited here. This leads to a recursive definition o
f the function start addresses in the jump table.
While this is not in itself dangerous, it prevents the real function referen
ces from being established and hence the overlaying process is inhibited.
***********************************************************;
*<<<<<<<<<<<<<Recursive Call To Segment Error>>>>>>>>>>>>>>*
***********************************************************;
#include <stdio.h>
#include <reg517.h>
void func1(void) {
unsigned char i1 ;
for(i1 = 0 ; i1 < 10 ; i1++) {
printf("THIS IS FUNCTION 1\n") ; // String stored in
?CO?MAIN1 segment
}
}
void func2(void) {
unsigned char i2 ;
for(i2 = 0 ; i2 < 10 ; i2++) {
printf("THIS IS FUNCTION 2\n") ; // String stored in
?CO?MAIN1 segment
}
}
code void(*jump_table[])()={func1,func2}; //Jump table to
functions,
// table stored in
?CO?MAIN1
// segment.
/*** Calling Function ***/
main() {
(*jump_table[P1 & 0x01])() ; // Call function via jump
table in ?CO?MAIN1
}
^^^^^^^^^^^^^^^^^^^^^^^ End of Module
The resulting link output is:
Note: No reference exists between main and func1/2 so the overlay process ca
nnot occur, resulting in wasted RAM.
OVERLAY MAP OF MODULE: MAIN1 (MAIN1)
MCS-51 LINKER / LOCATER L51 V2.8
DATE 04/08/92 PAGE 2
SEGMENT BIT-GROUP DATA-GROUP
+_> CALLED SEGMENT START LENGTH START LENGTH
________________________________________________________________
?C_C51STARTUP - - - -
+_> ?PR?MAIN?MAIN1
?PR?MAIN?MAIN1 - - - -
+_> ?CO?MAIN1
+_> ?C_LIB_CODE
?CO?MAIN1 - - - -
+_> ?PR?FUNC1?MAIN1
+_> ?PR?FUNC2?MAIN1
?PR?FUNC1?MAIN1 - - 0008H 0001H
+_> ?PR?PRINTF?PRINTF
?PR?PRINTF?PRINTF 0020H.0 0001H.1 0009H 0014H
+_> ?C_LIB_CODE
+_> ?PR?PUTCHAR?PUTCHAR
?PR?FUNC2?MAIN1 - - 0008H 0001H
+_> ?PR?PRINTF?PRINTF
*** WARNING 13: RECURSIVE CALL TO SEGMENT
SEGMENT: ?CO?MAIN1
CALLER: ?PR?FUNC1?MAIN1
*** WARNING 13: RECURSIVE CALL TO SEGMENT
SEGMENT: ?CO?MAIN1
CALLER: ?PR?FUNC2?MAIN1
8.4.2.4 Function Jump Table Warning Solution
The solution is to use the OVERLAY command when linking thus
main1.obj &
to main1.abs &
OVERLAY(?CO?MAIN1 ~ (func1,func2), main ! (func1,func2))
This deletes the reference to func1 & 2 from the ?CO?MAIN1 segment and inser
ts the true reference from main to func1 & func2.
The linker output is now thus:
OVERLAY MAP OF MODULE: MAIN1.ABS (MAIN1)
SEGMENT BIT-GROUP DATA-GROUP
+_> CALLED SEGMENT START LENGTH START LENGTH
________________________________________________________________
?C_C51STARTUP - - - -
+_> ?PR?MAIN?MAIN1
?PR?MAIN?MAIN1 - - - -
+_> ?CO?MAIN1
+_> ?C_LIB_CODE
+_> ?PR?FUNC1?MAIN1
+_> ?PR?FUNC2?MAIN1
?PR?FUNC1?MAIN1 - - 0008H 0001H
+_> ?CO?MAIN1
+_> ?PR?PRINTF?PRINTF
?PR?PRINTF?PRINTF 0020H.0 0001H.1 0009H 0014H
+_> ?C_LIB_CODE
+_> ?PR?PUTCHAR?PUTCHAR
?PR?FUNC2?MAIN1 - - 0008H 0001H
+_> ?CO?MAIN1
+_> ?PR?PRINTF?PRINTF
8.4.2.5 Multiple Call To Segment Warning
(Hazardous)
This warning generally occurs when a function is called from both the backgr
ound and an interrupt. This means that potentially the interrupt may call th
e function whilst it is still running, as a result of a background level cal
l. The result could be the over-writing of the local data in the background.
The fact that the offending function is also overlaid with other background
functions makes the chances of failure very high. The simplest solution is
to declare the function as REENTRANT so that the compiler will generate a lo
cal stack for parameters and variables. Thus on each call to the function, a
new set of parameters and local variables are created without destroying an
y existing ones from the current call.
Unfortunately this significantly increases the run time and code produced. A
nother possibility is to make a second and renamed version of the function,
one for background use and one for interrupt. This is somewhat wasteful and
presents a maintenance problem, as you now have effectively two versions of
the same piece of code.
In many cases the situation is not a problem, as the user may have ensured t
hat the reentrant use could never occur, but is left with the linker warning
. However this must be viewed as dangerous, particularly if more than one pr
ogrammer is involved.
#include <stdio.h>
#include <reg517.h>
void func1(void) {
unsigned char i1,a1[15] ;
for(i1 = 0 ; i1 < 10 ; i1++) {
a1[i1] = i1 ;
}
}
void func2(void) {
unsigned char i2,a2[15] ;
for(i2 = 0 ; i2 < 10 ; i2++) {
a2[15] = i2 ;
}
}
main() {
func1() ;
func2() ;
}
void timer0_int(void) interrupt 1 {
func1() ;
} ^^^^^^^^^^^^^^^^^^^^^^^ End of Module
This produces the linker map:
OVERLAY MAP OF MODULE: MAIN2 (MAIN2)
SEGMENT DATA-GROUP
+_> CALLED SEGMENT START LENGTH
?PR?TIMER0_INT?MAIN2
+_> ?PR?FUNC1?MAIN2
?PR?FUNC1?MAIN2 0017H 000FH
?C_C51STARTUP
+_> ?PR?MAIN?MAIN2
?PR?MAIN?MAIN2
+_> ?PR?FUNC1?MAIN2
+_> ?PR?FUNC2?MAIN2
?PR?FUNC2?MAIN2 0017H 000FH
D:0007H SYMBOL i1 // Danger!
D:0017H SYMBOL a1
D:0007H SYMBOL i2
D:0017H SYMBOL a2
*** WARNING 15: MULTIPLE CALL TO SEGMENT
SEGMENT: ?PR?FUNC1?MAIN2
CALLER1: ?PR?TIMER0_INT?MAIN2
CALLER2: ?C_C51STARTUP
8.4.2.6 Multiple Call To Segment Solution
The solution is to
(i) Declare func1 as REENTRANT thus:
void func1(void) reentrant { }
(ii) Use OVERLAY linker option thus:
main2.obj &
to main2.abs &
OVERLAY(main ~ func1,timer0_int ~ func1)
to break connection between main and func1 and timer0_int and func1.
OVERLAY MAP OF MODULE: MAIN2.ABS (MAIN2)
SEGMENT DATA-GROUP
+_> CALLED SEGMENT START LENGTH
___________________________________________________
?C_C51STARTUP - -
+_> ?PR?MAIN?MAIN2
?PR?MAIN?MAIN2 - -
+_> ?PR?FUNC2?MAIN2
?PR?FUNC2?MAIN2 0017H 000FH
*** WARNING 16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?FUNC1?MAIN2
This means that the safe overlaying of func1 with other background functions
will not occur. Removing the link only with the interrupt would solve this:
main2.obj &
to main2.abs &
OVERLAY(timer0_int ~ func1)
Another route would be to disable all overlaying but this is likely to eat u
p large amounts of RAM very quickly and is thus a poor solution.
main2.obj & to main2.abs & NOOVERLAY
With the MULTIPLE CALL TO SEGMENT WARNING the only really "safe" solution is
to declare func1 as REENTRANT, with the duplicate function a good second. T
he danger of using the OVERLAY command is that a less experienced programmer
new to the system might not realise that the interrupt is restricted as to
when it can call the function and hence system quality is degraded.
8.4.3 Overlaying Public Variables
All the preceding examples deal with the overlaying of locals and parameters
at a function level. A case occurred recently in which the program was spli
t into two distinct halves; the divide taking place very early on. To all in
tents a_nd purposes the 8051 was able to run one of two completely different
application programs, based on some user input during initialisation.
Each program half had a large number of public variables, some of which were
known to both sides but the majority of which were local to one side only.
This is almost multitasking.
This type of program structure really needs a new storage class like "GLOBAL
", with public meaning available to a certain number of modules only. GLOBAL
would then be available to all modules. The new C166 supports this type of
task-based variable scope. Unfortunately C51 does not, so a fix is required.
The linker's OVERLAY command does not help, as it only controls the overlayi
ng of local and parameter data. One possible solution uses special modules t
o declare the publics. Module1 declares the publics for program (task1); Mod
ule2 declares the publics for program2 (task2). Finally, Module3 declares th
e publics which are available to both sides.
The trick then is to use the linker to fix the data segments on Module1 and
Module2 at the same physical address, whilst allowing Module3's variables to
be placed automatically by the linker.
This solution uses three special modules for declaring the publics:
/* Example of creating two sets of public data */
/*in same memory space */
extern void main1(void) ;
extern void main0(void) ;
/* Main module where system splits into two parts */
void main(void) {
bit flag ;
if(flag) {
main0() ; // Branch 0
}
else {
main1() ; // Branch 1
}
} ^^^^^^^^^^^^^^^^^^^^^^^ End of Module
/* Module that declares publics for branch 2 */
/* Publics for branch 2 */
unsigned char x2,y2 ;
unsigned int z2 ;
char a2[0x30] ;
/* A variable which is accessible from both branches */
extern int common ;
^^^^^^^^^^^^^^^^^^^^^^^ End of Module
void main0(void) {
unsigned char c0 ; /* Local - gets overlaid with c1 in*/
/*other branch */
x2 = 0x80 ;
y2 = x2 ;
c0 = y2 ;
z2 = x2*y2 ;
a2[2] = x2 ;
common = z2 ;
}
^^^^^^^^^^^^^^^^^^^^^^^ End of Module
/* Module that declares publics for branch 1 */
/* Publics for branch 1 */
unsigned char x1,y1 ;
unsigned int z1 ;
char a1[0x30] ;
/* A variable which is accessible from both branches */
extern int common ;
void main1(void) {
char c1 ;
x1 = 0x80 ;
y1 = x1 ;
c1 = y1 ;
z1 = x1*y1 ;
a1[2] = x1 ;
common = z1 ;
}
^^^^^^^^^^^^^^^^^^^^^^^ End of Module
/* Module that declares variables that both */
/*branches can access */
int common ; /* A variable common to both branches */
^^^^^^^^^^^^^^^^^^^^^^^ End of Module
/* Linker Input */
l51 t.obj,t1.obj,t2.obj,com.obj to t.abs
DATA(?DT?T1(20H),?DT?T2(20H))
The choice of "20H" for the location places the combined segments just above
the register banks.
The main problem with this approach is that a DATA overlay warning is produc
ed. This is not dangerous but is obviously undesirable.
----------------------------------------------------------------------------
----
--
Ours is essentially a tragic age, so we refuse to take it tragically.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -