[U-Boot] the processor performs an operation overflows,U-boot-based platform

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?

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; }
Didn't read this carefully but figured I should make one comment, overflow handling for signed int's are undefined in C and gcc uses that when optimizing. Use unsigned int's instead.
Jocke
participants (2)
-
Joakim Tjernlund
-
liu yue