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;
}