[U-Boot] the processor performs an operation overflows,U-boot-based platform
liu yue
bitliu1983 at gmail.com
Wed May 18 04:43:59 CEST 2011
unsigned long get_tbus (void)
{
unsigned long tbl=0;
unsigned long tbu1=0, tbu2=0;
unsigned long us=0;
unsigned long long tmp=0;
unsigned long tbclk = os_get_tbclk();
// get the timebase ticks
do {
__asm__ __volatile__ ("mftbu %0":"=r" (tbu1):);
__asm__ __volatile__ ("mftb %0":"=r" (tbl):);
__asm__ __volatile__ ("mftbu %0":"=r" (tbu2):);
} while (tbu1 != tbu2);
// convert ticks to ms
tmp = (unsigned long long)(tbu1);
tmp = (tmp << 32);
tmp += (unsigned long long)(tbl);
us = tmp / (tbclk / 1000000);
return us;
}
void main()
{
unsigned long uiTBusB,s_uiTBusA;
while(1)
{
s_uiTBusA = uiTBusB;
uiTBusB = (get_tbus() / 1000);
printf("uiTBusB:%d,%u\n",uiTBusB,uiTBusB);
sleep(100);
}
}
Different performance results, the code is as follows: My platform is
mpc8313, core is the e300, running 30 minutes later when there will be:
uiTBusB overflow occurred. get_tbus () = 0x8001A69B, but uiTBusB =
4292819925
but modify the function as follows:
unsigned long get_tbus (void)
{
unsigned long us =0x8001A69B
return us;
}
uiTBusB overflow does not occur,the results are normal. why only run 40
minutes later, the program will overflow, on the contrary, directly modify
the function return value, no overflow.. With the compiler set the
parameters related?
I use the compiler powerpc-e300c3-linux-gcc-4.0.2.
When powerpc perform mathematical operations, such as: get_tbus () / 1000,
the implementation of the multiplication instruction, the function return
value unsigned numbers as signed to carry out operations, resulting in
operation result overflows?
us = tmp / (tbclk / 1000000);
may be a source of the problem.unsigned long long and unsigned long
variables casted to each other .
I used to test the code as followed:
s_uiTBusA = uiTBusB;
uiTBusB = (get_tbus() / 1000);
printf("main:SA:%u; SB:%u; SB-SA:%d.\n", s_uiTBusA, uiTBusB,
uiTBusB-s_uiTBusA);
I know that when overflow occurs, get_tbus () the value is generally just
over 0x80000000,
2.tbclk = (0x7de2900 + 3L) / 4L = 33000000; us = tmp / (tbclk / 1000000);
I'm not sure if there are problems, but when tested for a long period of
time is no problem . tmp is unisgned long long integer, it overflow take
many years, so how can verify that the conversion is no problem? ? Function
unsigned long get_tbus (void) return value in some cases become negative,
overflow it?
More information about the U-Boot
mailing list