MOD5213 iprintf() error for UL and ULL types?

Discussion to talk about software related topics only.
joepasquariello
Posts: 85
Joined: Mon Apr 28, 2008 7:32 am

MOD5213 iprintf() error for UL and ULL types?

Post by joepasquariello »

On the MOD5213, iprintf() seems to have a problem with printing unsigned long (UL) and unsigned long long (ULL) values with more than 9 digits. The code below shows output of UL and ULL values > 1,000,000,000 (10 digits). Only the last 9 digits are printed by iprintf(), while all digits are produced correctly by printf(). Is this a known issue with the MOD5213 library? I'm pretty sure this works correctly on the MOD5234.

Joe

// define and initialize UL with 10 digits (max) and ULL with 20 digits (max)
unsigned long long ULL = (0xFFFFFFFF << 32) + 0xFFFFFFFF;
unsigned long UL = 0xFFFFFFFF;

// print UL and ULL values using iprintf() and printf()
iprintf( "iprintf: UL = %lu, ULL = %llu\r\n", UL, ULL );
printf ( "printf: UL = %lu, ULL = %llu\r\n", UL, ULL );

// incorrect output (least sig. 9 digits) for iprintf(). correct output for printf().
iprintf: UL = 294967295 ULL = 294967295
printf: UL = 4294967295 ULL = 18446744073709551615
User avatar
tod
Posts: 587
Joined: Sat Apr 26, 2008 8:27 am
Location: Southern California
Contact:

Re: MOD5213 iprintf() error for UL and ULL types?

Post by tod »

I just tried it on a 5272 (for one more data point) and it iprints correctly there as well. Does the MOD5213 have a unique stdio.h file? I would have thought all the platforms shared nburn\gcc-m68k\m68k-lef\include\stdio.h and I therefore assumed the code itself was in NetBurner.a not MOD5272.a, but you know what they say about assumptions.

Maybe try doing it with straight literals (no variables) like shown below and another data point might be to try cout.
<iostream>
std::cout<< 0xFFFFFFFF <<std::endl;
does too.
Attachments
UnsignedLong.png
UnsignedLong.png (30.74 KiB) Viewed 9159 times
User avatar
tod
Posts: 587
Joined: Sat Apr 26, 2008 8:27 am
Location: Southern California
Contact:

Re: MOD5213 iprintf() error for UL and ULL types?

Post by tod »

I just took a quick glance at the 5213 data sheet, on second thought don't try cout, you'll probably run out of memory.
joepasquariello
Posts: 85
Joined: Mon Apr 28, 2008 7:32 am

Re: MOD5213 iprintf() error for UL and ULL types?

Post by joepasquariello »

Tod,

MOD5213 iprintf() shows problem for both variables and literals.
MOD5234 iprintf() works fine.

I would not have guessed that iprintf() would be different for MOD5234 and MOD5213, but it seems to be. While searching for information on this problem, I found NetBurner history for NNDK 2.1, which include the item below. Perhaps this fix was never made to the iprintf() that gets linked to the MOD5213 library.

Version 1.78: Fixed library bug so iprintf and printf support long variables.

64-bit integer math (LL and ULL) works fine in the MOD5213. It's just the iprintf() that doesn't work correctly.

Joe
joepasquariello
Posts: 85
Joined: Mon Apr 28, 2008 7:32 am

Re: MOD5213 iprintf() error for UL and ULL types?

Post by joepasquariello »

I did some searching around regarding GCC iprintf(), and stumbled on a discussion of NetBurner vs. Rabbit from 2004 that included the quote below from Paul Breed, NetBurner CTO. The 5213 has much less resources than the 5234, so maybe they are using a different library code base.
In 5 years we have had exactly 3 GCC/NewLib problems. All were actualy in NewLib
1)Printf did not support long long variables.
2)malloc had a reentrancy problem.
3)floating point printf reentrancy problem.
Paul, if you read this, could you let us know if the problems with "long" and "long long" are fixable for iprintf() in the MOD5213?

Joe
User avatar
pbreed
Posts: 1088
Joined: Thu Apr 24, 2008 3:58 pm

Re: MOD5213 iprintf() error for UL and ULL types?

Post by pbreed »

not sure the netbuner iprintf supports long long.
The bung in the unsigned long was also on the SBL2E platform and that got fixed.

To fix the problem


nburn\system_nn\nbiprintf.cpp

Change
From:
int decimallen( DWORD dw )
{
if ( dw >= 100000000 ) return 9;
if ( dw >= 10000000 ) return 8;
if ( dw >= 1000000 ) return 7;
if ( dw >= 100000 ) return 6;
if ( dw >= 10000 ) return 5;
if ( dw >= 1000 ) return 4;
if ( dw >= 100 ) return 3;
if ( dw >= 10 ) return 2;
return 1;
}

to:
int decimallen( DWORD dw )
{
if (dw >=1000000000 ) return 10;
if ( dw >= 100000000 ) return 9;
if ( dw >= 10000000 ) return 8;
if ( dw >= 1000000 ) return 7;
if ( dw >= 100000 ) return 6;
if ( dw >= 10000 ) return 5;
if ( dw >= 1000 ) return 4;
if ( dw >= 100 ) return 3;
if ( dw >= 10 ) return 2;
return 1;
}
User avatar
pbreed
Posts: 1088
Joined: Thu Apr 24, 2008 3:58 pm

Re: MOD5213 iprintf() error for UL and ULL types?

Post by pbreed »

The netburner small printf on the MOD5213 does not support long long.
(Previous post should fix the unsigned long problem., that fix is now checked in and should eventually appear in a release.)

It could be modified... but forcing the libraries to link in the 64 bit math stuff
would be a loss for most applications.
joepasquariello
Posts: 85
Joined: Mon Apr 28, 2008 7:32 am

Re: MOD5213 iprintf() error for UL and ULL types?

Post by joepasquariello »

Hi Paul,

Thanks very much for your help. I made the source change and rebuilt the system_nn library, and got a good result for UL as shown below. The output of iprintf() is now 10 digits instead of 9. As you said, trying to print a ULL just prints 32 bits instead of 64.

iprintf: UL = 4294967295, ULL = 4294967295
printf: UL = 4294967295, ULL = 18446744073709551615

Regarding your last comment, you're saying that if iprintf() had been written to support 64-bit values, it would have caused all 64-bit math routines to be linked? Now that I look at the iprintf() source, I see that math operations are required for printing, so it makes sense. I'll experiment and see what happens to code size when 64-bit math is used, but no floating point is used. I had never used 64-bit integers on a NB project until I tried to make an integer version of Larry's StopWatch. If ever wanted to use that in a space-limited project on the 5213, I'd be better off trying to make a version limited to times that fit in 32 bits.

Joe
KE5FX
Posts: 25
Joined: Tue Dec 10, 2019 11:17 pm

Re: MOD5213 iprintf() error for UL and ULL types?

Post by KE5FX »

Is this still the case, 9 years later? I'm having trouble using %Ld with sprintf() on NNDK 3.2 with the MODM7AE. Lockups, garbage characters, and the like.

I can print 64-bit ints with some of the other functions, just not sprintf().
User avatar
TomNB
Posts: 573
Joined: Tue May 10, 2016 8:22 am

Re: MOD5213 iprintf() error for UL and ULL types?

Post by TomNB »

Hello,

Perhaps I am misunderstanding your question, but I ran a quick test on 3.2 with the MODM7 with the following results:

Code: Select all

void UserMain(void * pd)
{
    init();
    WaitForActiveNetwork(TICKS_PER_SECOND * 5);   // Wait up to 5 seconds for active network activity 
    StartHttp();

    iprintf("Application %s started\n",AppName );

    char buf[2048];

    uint32_t uint32Int = 0x12345678;
    printf("printf ld uint32_t decimal: %ld, 0x%lx\r\n", uint32Int, uint32Int);
    printf("printf lu uint32_t decimal: %lu, 0x%lx\r\n", uint32Int, uint32Int);

    sprintf(buf, "sprintf ld uint32_t decimal: %ld, 0x%lx", uint32Int, uint32Int);
    printf("%s\r\n", buf);
    sprintf(buf, "sprintf lu uint32_t decimal: %lu, 0x%lx", uint32Int, uint32Int);
    printf("%s\r\n", buf);

    uint64_t uint64Int = 0x123456789ABCDEF0;
    printf("printf lld  uint64_t decimal: %lld, 0x%llx\r\n", uint64Int, uint64Int);
    printf("printf llu  uint64_t decimal: %llu, 0x%llx\r\n", uint64Int, uint64Int);

    sprintf(buf, "sprintf lld uint64_t decimal: %lld, 0x%llx", uint64Int, uint64Int);
    printf("%s\r\n", buf);
    sprintf(buf, "sprintf llu uint64_t decimal: %llu, 0x%llx", uint64Int, uint64Int);
    printf("%s\r\n", buf);

    while (1)
    {
        OSTimeDly(TICKS_PER_SECOND);
    }
}
Output:
Application AppWiz started
printf ld uint32_t decimal: 305419896, 0x12345678
printf lu uint32_t decimal: 305419896, 0x12345678
sprintf ld uint32_t decimal: 305419896, 0x12345678
sprintf lu uint32_t decimal: 305419896, 0x12345678

printf lld uint64_t decimal: 1311768467463790320, 0x123456789abcdef0
printf llu uint64_t decimal: 1311768467463790320, 0x123456789abcdef0
sprintf lld uint64_t decimal: 1311768467463790320, 0x123456789abcdef0
sprintf llu uint64_t decimal: 1311768467463790320, 0x123456789abcdef0

Is there anything here different from what you are doing?
Post Reply