bug in redlib

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

bug in redlib

803件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mcu_programmer on Sun Oct 17 08:24:00 MST 2010
long long (64 bit integer) division can hang execution of the code when using redlib library. If I instead compile with newlib, the same code works.

I've noticed that if you have a function with long long, and then in main() have long long, divsion in main() hangs the execution.

In the code below, execution hangs between the uart message 1 and 2.


#include "LPC11xx.h"
#include "uart.h"
// red_lib division bug with 64 bit numbers
// long long i
// division with i hangs system

volatile long interupt=0;
void get_stat(short *arr, long len, long *average, long *median, long *std_dev, char *stick_out, long target, long *std_dev_target);
unsigned long isqrt(unsigned long long int x);
int main(void) {
char i;
unsigned long long sum=0, sum2=0;
char stick_out;
long len, average, median, std_dev, target,std_dev_target,j;
short arr[10] = {1231, 1125, 1628, 1925, 1172,1523,1264,1236,1237,1102};

/* Enable AHB clock to the GPIO domain. */
   LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);

   UARTInit(19200);

   //Red Lib bug
   len = 10;

   send_str("START RED_LIB BUG\r\n");
   target = 2000;
   get_stat(arr,10, &average, &median, &std_dev, &stick_out, target, &std_dev_target);

   send_str("FINSHED TEST\r\n");


   return 0 ;
}

void send_str(char *str)
{
long i;
for (i=0; str; i++)
{
while ((LPC_UART->LSR & LSR_THRE) == 0)
;
LPC_UART->THR = str;
}
}

void get_stat(short *arr, long len, long *average, long *median, long *std_dev, char *stick_out, long target, long *std_dev_target)
{
long i, j, tmp, min;
short mult=0, mult2=0;
unsigned long long sum=0, sum2=0;

for (i=0; i < len; i++)
{
min = arr;
for (j=i; j<len; j++)
{
if (arr[j] < min)
{
min = arr[j];
tmp = arr;
arr = arr[j];
arr[j] = tmp;
}
}
}
*median = arr[len/2];
*average = 0;
for (i=0; i<len; i++)
{
*average += arr;
}

*average /= len;

for (i=0; i<len; i++)
{
sum += (arr - *average)*(arr - *average);
sum2 += (arr - target)*(arr - target);
}

send_str("1\r\n");
sum /= len;
send_str("2\r\n");
sum2 /= len;
send_str("3\r\n");

*stick_out=0;
for (i=0; i<len; i++) // find out how many double std_dev
{
if ( (arr - *average)*(arr - *average) > (sum)*4)
{
   (*stick_out)++;
}
}
send_str("4\r\n");
*std_dev = isqrt(sum);
send_str("5\r\n");
*std_dev_target = isqrt(sum2);
send_str("6\r\n");
}
unsigned long isqrt(unsigned long long int x)
{
unsigned long long int a = 0;
unsigned long long int a2 = 0, t;
    signed long k;

    for (k = 31; k >= 0; k--) {

t = a2 + (a << (k+1)) + ((long long)1 << (k + k));
if (x > t) {
    a += 1 << k;
    a2 = t;
}
    }

    return a;
}
0 件の賞賛
返信
4 返答(返信)

782件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by CodeRedSupport on Mon Oct 18 12:56:00 MST 2010
That is not a bug.

The gcc compiler for ARM, defines "char" as unsigned (*). If you want it to be signed, use "signed char", or the compiler switch -fsigned- char which makes ALL chars signed.

(*) From Dr Dobbs Journal:
http://www.drdobbs.com/184405435

What's the range of the [I]char[/I] data type? The answer is "undefined." The ANSI C Standard specifies the range only for signed and unsigned [I]char[/I]s. Signed [I]char[/I]s are at least -127 to 127, while unsigned [I]char[/I]s are at least 0 to 255. As for simple [I]char[/I]s, the Standard lets the compiler decide whether they are signed or unsigned.
<snip>
You'll find no single "load character from memory and sign extend" in  the ARM instruction set. That's why, for performance reasons, every  compiler I'm aware of makes the default [I]char[/I] type signed on x86, but unsigned on ARM. (A workaround for the GNU GCC compiler is the [I]-fsigned-[/I] [I]char[/I] parameter, which forces all [I]char[/I]s to become signed.)
0 件の賞賛
返信

782件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rkiryanov on Mon Oct 18 12:51:45 MST 2010

Quote: mcu_programmer
If you do replace the first line with
short i;
then the code works as it should.



Try signed char.
0 件の賞賛
返信

782件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mcu_programmer on Mon Oct 18 12:23:57 MST 2010
With the release 3.5, I suggest you fix a compiler bug too.

This code hangs,

char i;

for (i=10; i>=0; i--)
   ;

If you do replace the first line with

short i;

then the code works as it should.
0 件の賞賛
返信

782件の閲覧回数
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by CodeRedSupport on Mon Oct 18 01:52:22 MST 2010
Thank you for providing a test case for the issue you have encountered.

There does indeed appear to be a problem with code using long long divides built for Cortex-M0/LPC11xx. ( Note that this problem does not exist when building code for Cortex-M3 based parts [LPC13/LPC17]. ) The problem is not in Redlib as such, but actually in the "ARM EABI" support library that is linked with when Redlib is used (though I admit that from a user viewpoint this is somewhat academic).

We will fix this issue in the next release of LPCXpresso (current release today being 3.5.0). In the meantime, if you would like to test out a beta of the support library with this long long divide problem fixed, please contact us directly via the " email: support" link at:

http://www.code-red-tech.com/support.php

referencing this forum post.

One final note, this problem does not exist in the "Redlib_v2" supplied as part of the LPCXpresso for Linux beta - which uses a new implementation of the ARM EABI support functions.

Regards,
CodeRedSupport.
0 件の賞賛
返信