Author Topic: Simulator vs. GCC  (Read 29246 times)

Offline paulk

  • Newbie
  • *
  • Posts: 45
    • View Profile
Simulator vs. GCC
« on: November 18, 2009, 03:45:40 PM »
I'm making progress in learning uTasker, but I'm having problems with the seemingly "simple" stuff.

I'm playing with dynamic web content (in terms of fnInsertString).  I took the advice to remove all the stuff from the sample fnInsertString function (webinterface.c) and start replacing it with what I need.  So far, I have the following:

Code: [Select]
if(!TxLength)  //simple string field
{
  switch(*ptrBuffer++)
  {
    case 'N':  //insert STRING
  uStrcpy(&cValue, "Test");
  *usLengthToSend=4;
  break;
case 'I':  
  *usLengthToSend=sprintf(&cValue, "%u", uTaskerSystemTick);
  break;
    default:
  *usLengthToSend=0;
  }


      return cValue;
}

I want the "£vI" directive to write the system tick value.  The above code works fine in the simulator, but when I try to compile it using GCC, it dies with a bunch of warnings and errors.  Specifically, it doesn't like the sprintf call.  Here are some of the warnings / errors:

Code: [Select]
C:\dev\uTasker\Applications\uTaskerV1.4\GNU_LM3SXXXX>cs-make -f make_uTaskerV1.4_GNU_LM3SXXXX all
arm-none-eabi-gcc -mcpu=cortex-m3 -mlittle-endian -mthumb -Wall -Wstrict-prototypes -I../../uTaskerV1.4 -D _GNU -D _LM3SXXXX -g -c -Os ../webInterface
.c -o Build/webInterface.o
../webInterface.c: In function 'fnInsertString':
../webInterface.c:646: warning: implicit declaration of function 'sprintf'
../webInterface.c:646: warning: incompatible implicit declaration of built-in function 'sprintf'
../webInterface.c:646: warning: format '%u' expects type 'unsigned int', but argument 3 has type 'UTASK_TICK'

The warnings I generally understand, but where it dies is during linking I think, with the following:
Code: [Select]
arm-none-eabi-gcc -mcpu=cortex-m3 -mlittle-endian -mthumb -Wall -Wstrict-prototypes -I../../uTaskerV1.4 -D _GNU -D _LM3SXXXX -g -Os -Wl,-Map=uTaskerV1
.4.map --no-gc-sections -nostartfiles -TuTaskerLM3SXXXX.ld -o uTaskerV1.4.elf Build/application.o Build/debug.o Build/webInterface.o Build/KeyScan.o B
uild/CGLCD.o Build/OLED.o Build/LCD.o Build/NetworkIndicator.o Build/usb_application.o Build/LM3SXXXX.o Build/MODBUS.o Build/modbus_app.o Build/GLCD.o
 Build/eth_drv.o Build/Driver.o Build/uMalloc.o Build/uTasker.o Build/Tty_drv.o Build/iic_drv.o Build/USB_drv.o Build/uFile.o Build/Watchdog.o Build/G
lobalTimer.o Build/low_power.o Build/Ethernet.o Build/arp.o Build/dhcp.o Build/dns.o Build/ftp.o Build/http.o Build/icmp.o Build/ip_utils.o Build/ip.o
 Build/pop3.o Build/smtp.o Build/snmp.o Build/tcp.o Build/telnet.o Build/tftp.o Build/udp.o Build/webutils.o Build/NetBIOS.o
c:/dev/codesourcery/sourcery g++ lite/bin/../lib/gcc/arm-none-eabi/4.4.1/../../../../arm-none-eabi/bin/ld.exe: section .ARM.exidx loaded at [00000000,
00000007] overlaps section .vectors loaded at [00000000,00000007]
c:/dev/codesourcery/sourcery g++ lite/bin/../lib/gcc/arm-none-eabi/4.4.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-sbrkr.o): In function `_sbr
k_r':
sbrkr.c:(.text+0x12): undefined reference to `_sbrk'
collect2: ld returned 1 exit status
cs-make: *** [uTaskerV1.4.elf] Error 1

If I take out the sprintf, it works.

I have tried adding stdio.h to webinterface.c, but that didn't work.  So, can I use sprintf?  Is there a list of functions that I can/can't use?  Are all standard C functions ie: via (stdio, stdlib) supported?

My research on the internet tells me that sprintf probably uses malloc(), and malloc in turn calls this "_sbrk" function which doesn't exist. 

Offline mhoneywill

  • Full Member
  • ***
  • Posts: 173
    • View Profile
Re: Simulator vs. GCC
« Reply #1 on: November 18, 2009, 05:31:50 PM »
Hi Paul,

I hit this issue too, but Mark has implemented his own string functions which are very efficient and do not rely on printf/sprintf. The problem is that sprintf can be VERY hungry on memory. I would suggest you look at Marks string functions.

I presume you are using uTasker V1.4 because the string functions were rationalised in this version. This link documents the string functions
http://www.utasker.com/forum/index.php?topic=641.0

Also see http://www.utasker.com/forum/index.php?topic=571.0 and http://www.utasker.com/forum/index.php?topic=30.0

Hope this helps

Cheers

Martin



Offline paulk

  • Newbie
  • *
  • Posts: 45
    • View Profile
Re: Simulator vs. GCC
« Reply #2 on: November 18, 2009, 06:39:30 PM »
Thanks Martin,

I did end up coming across those threads after-the-fact, but I'm glad you sent me the link to the functions, as I hadn't seen that.

I typically avoid use of (s)printf functions, coming from an 8-bit micro background, but they do have their place, and can make coding life much easier in some circumstances. (I've used them successfully and extensively in 8-bit processors).

I also came across a few links with regards to this issue specific to Luminary Micro and CodeSourcery GCC.  It looks like the srbk function can cause issues:

http://embdev.net/topic/129753

There is even an "Urban Dictionary" entry for this  ;D

http://www.urbandictionary.com/define.php?term=undefined%20reference%20to%20_sbrk

Interestingly enough I found some documentation on the fact in some of the GCC literature installed with the CodeSourcery GCC, under the "syscalls.html" file.

/CodeSourcery/Sourcery G++ Lite/share/doc/arm-arm-none-eabi/html/libc/Syscalls.html

It goes on to mention that you may need to provide "Stubs" of certain code to enable the links to libc. 

I wonder if there are pre-written "stub" files for this task.  I will try to avoid using the (s)printf functions, but as I said, in some cases they are useful eg: printing floating point numbers.  Which functions do you recommend for this task?

Offline mhoneywill

  • Full Member
  • ***
  • Posts: 173
    • View Profile
Re: Simulator vs. GCC
« Reply #3 on: November 18, 2009, 07:45:45 PM »
Hi Paul,

Although I use GCC, I use Rowley crossworks, who have created their own libs.

Sorry for the short answer, I'm leaving the office

Martin

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: Simulator vs. GCC
« Reply #4 on: November 18, 2009, 11:53:14 PM »
Hi Paul

Take a look at the following thread: http://www.utasker.com/forum/index.php?topic=489.0
It discusses adding some standard library support whereby the _sbrk (and other stubs) are sometimes missing from the GCC library (expected to be added I believe in specific configuration). It was found not to be an issue by some GCC builds but them missing in another.

To use printf() etc. you will need to add a stub of some sort or possibly putchar(), which sends each byte over a serial interface. It may be adequate to add a define to replace putchar(&char) with fnWrite(uart_handle, &char, 1) or similar.

Regards

Mark

Offline paulk

  • Newbie
  • *
  • Posts: 45
    • View Profile
Re: Simulator vs. GCC
« Reply #5 on: November 19, 2009, 12:11:37 AM »
Hi Mark,

Thanks for the followup.  I've been researching this issue all day.  I will experiment with adding the stub file information myself.  I expect however that the sprintf function will cause considerable code bloat (although in my experience with 8-bit micros, it was acceptable in some cases where quick formatting was required).  I was hoping that this type of thing would be straight-forward, but as luck would have it, sometimes the seemingly simple things end up being the hardest.

Can you comment on uTasker + LM parts with floating point numbers?  I will require some FP math (simple add/subtract/multiply/divide).  But I will need a method to print those numbers.  I can do without sprintf for floats (ie: try to use a simpler implementation such as the usprintf included with StellarisWare, but how would I convert float to string?


Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: Simulator vs. GCC
« Reply #6 on: November 19, 2009, 12:42:06 AM »
Hi Paul

I think that a library routine to convert floats to a string is the only real way to go. Once you have it as a string it can be sent to an output using fnDebugMsg() or similar. Since sprintf() should be pure software I wouldn't expect any HW stubs to be required - it may however use malloc() which would bring the library heap in to play. Check out the following at the Luminary forum http://www.luminarymicro.com/component/option,com_joomlaboard/Itemid,92/func,view/catid,6/id,3976/#3976

Regards

Mark

Offline paulk

  • Newbie
  • *
  • Posts: 45
    • View Profile
Re: Simulator vs. GCC
« Reply #7 on: November 19, 2009, 02:48:08 AM »
Thanks Mark,

Unfortunately, sprintf does use malloc(), and as a result requires the syscalls, which CodeSourcery GCC doesn't seem to provide...or not that I can find.  I've read mention of including libnosys.a, but I can't find such a file.

Additionally, going this route seems like tremendous overkill, and it sounds like the code bloat from this approach is immense....my previous 8-bit experience showed that it was manageable, so I'm a little frustrated that this is so difficult, given the greater processing power here.  According to this post:

http://www.luminarymicro.com/component/option,com_joomlaboard/Itemid,/func,view/catid,8/id,409/#409

In the case of the luminary version, it is almost 30k!!!!!

However, I'm not sure how to implement libnosys (-lnosys).  I've tried adding it in the linker in the makefile, but it fails (it says it can't find it), and a search through all the directories doesn't list it either.  This was a rather old post, so I'm not sure if maybe they removed it.

I'm a little confused though.  It looks like these functions (srbk, etc), are expected to exist in the operating system.  However, the CodeSourcery GCC toolchain is designed for processors without any OS, so how are these functions supposed to work?

My concern is that I don't want to screw up the memory management that uTasker is doing, with the "malloc" requirements of a single function (sprintf).  I'd accept implementing my own sprintf (or even ftoa), but I can't find one that seems to work.  Many of the ftoa functions butcher the numbers because of multiplication and division routines.

Offline paulk

  • Newbie
  • *
  • Posts: 45
    • View Profile
Re: Simulator vs. GCC
« Reply #8 on: November 19, 2009, 04:12:29 AM »
As an update, I tried toying with the suggestions in this thread:

http://www.utasker.com/forum/index.php?topic=489.0

But I have a lot of problems:

1) NULL was not defined anywhere.  I fixed this by setting a #define NULL 0
2) I adjusted the HEAPSIZE to 8192 as suggested
3) Code STILL wouldn't compile....it gave me error as follows:
Code: [Select]
..../ld.exe: section .ARM.exidx loaded at [00000000,00000007] overlaps section .vectors loaded at [00000000,00000007]4) I changed the .vectors section in the uTaskerLM3SXXXX.ld file to start at offset 0x00000008 instead.
5) This worked (code compiled), however loading it onto board caused it to not function
6) I removed the call to sprintf, and reverted the .vectors section to offset 0x0000000.  I compiled (successfully) the code, but left the _srbk function inside the application.c file.  However, with this bin, the board wouldn't work either...!!!

So I'm officially stuck, tired and out of ideas.  I need an efficient way to print float numbers, but this seemingly simple task is a major roadblock at this point.

Any ideas would be appreciated.


Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: Simulator vs. GCC
« Reply #9 on: November 19, 2009, 03:50:14 PM »
Hi Paul

As you probably already realise, this is GCC (and exact version) related. By changing to a newer or older release it may then work or stop working as I have experienced with the malloc() investigation.

Note that it is probably generally beneficial to use Rowley Crossworks (GCC based) since they add their own libraries and then it is also ensured (or at least very probably) then everything fits together nicely. Possibly CodeSourcery also offers similar stuff for paying users.

Since the routines that you are interested in require malloc() this must first be solved, whereby there shouldn't be any real problem since this has been investigated before and a working solution should essentially be available. Then the necessary library(s) for the floating point display use needs to be identified and hope that it doesn't bring in missing stubs which then need to be solved.... I never did this before with GCC so will also need to experiment.

I know that floating point and displaying this format is quite popular in the Coldfire project with CodeWarrior. In this case it is pretty much a case of linking the CW floating point library and then it is solved. But that doesn't help you...

Can you tell me exactly which version of CS GCC you are using - as mentioned before things can change between versions so it is important to check with the exact same one.

Regards

Mark

Offline paulk

  • Newbie
  • *
  • Posts: 45
    • View Profile
Re: Simulator vs. GCC
« Reply #10 on: November 19, 2009, 04:17:49 PM »
Hi Mark,

Thanks for the continued support and fast responses.

I do realize that this is a GCC issue, and I now know (and appreciate) why you use non-library versions of functions specifically in uTasker (uMalloc, uStrlen, etc).

At one point I was able to compile the code (although it didn't actually work), and the difference in code size was at least 20k.  I consider that to be excessive for one function.  Perhaps Rowley's implementation is better but at $3,000 for a commercial license, I consider that excessive too.

I have relegated myself to the fact of writing my own ftoa function (once it is cleaned up, I will post it here).  I found a few pre-written snippets on-line, but I found that they clobbered the numbers by doing multiplications and divisions.  I will then try to use the StellarisWare version of sprintf (simplified, no float support), in conjunction with my ftoa routine (ie: convert float to string, and then use it within sprintf).

The funny part is that the stuff that should be hard (ie: ethernet, filesystem, http, ftp) has been made a breeze using your tools, and the stuff that I've taken for granted (converting numbers to strings) has been a minor nightmare.  I spent way too much time on that problem last night (as my "Total time logged in" would prove!! :))

However, the upside is that I've learned a lot (still much much much more to go)!

As an aside, it would be satisfying (although probably irrelevant to my problem now) to figure this whole malloc() thing out.  I'm using the "arm-none-eabi-gcc.exe (Sourcery G++ Lite 2009q3-68) 4.4.1" version of the CS GCC Lite.

It appears to be missing the libnosys.a (which likely would solve the issue??), and when implementing my own _sbrk function, I got the linker error above about the .ARM.exidx. overlap.

Offline mhoneywill

  • Full Member
  • ***
  • Posts: 173
    • View Profile
Re: Simulator vs. GCC
« Reply #11 on: November 19, 2009, 07:46:45 PM »
Just a comment, but Crossworks is $1500 for a comercial licence not $3000. One reason I went with Crossworks was that they had written their own libraries. This point is often missed when people compare GCC to IAR and Keil. Have you tried using the code red suite http://code-red-tech.com/index.php its also GCC based, but with their own libraries.

Cheers

Martin

Offline paulk

  • Newbie
  • *
  • Posts: 45
    • View Profile
Re: Simulator vs. GCC
« Reply #12 on: November 19, 2009, 07:58:02 PM »
You're right.  My fault, I don't know where I got the $3k from (Looking at too many numbers over the last 12 hours...)  ;)

I haven't tried Crossworks or Code-Red.  I was quite happy that I had a "working" solution with CS GCC, but I'm starting to see the benefit of going a commercial route.  We're still testing the waters on the feasibility of the devices, toolchains, etc, etc, but we may make the plunge at some point.  As an aside, I can't stand Eclipse.  I know everyone uses it, and there must be a learning curve, and once you figure it out, its probably great, but I find it terribly unintuitive.

I'm curious: what is the approximate code penalty for implementing a sprintf function with floats in Crossworks?

Cheers,
Paul



Offline mhoneywill

  • Full Member
  • ***
  • Posts: 173
    • View Profile
Re: Simulator vs. GCC
« Reply #13 on: November 19, 2009, 08:46:00 PM »
If you can't stand Eclipse (Code red use it) Rowley are VERY good on eval licences, we evaluated for 3 or 4 months because I was dipping in and out of the project.
They also support a wide range of chips. Might be worth going the eval route with them and as its GCC based a switch to another IDE would be fairly easy. One point to note is that Marks builds for uTasker are based on Crossworks V1.7 and the new version is V2. I still use V1.7 as I'm mid project and don't have time to change, and I know a couple of things have changed see http://rowley.zendesk.com/forums/51134/entries/46164 which is the following comment. There may also be other minor changes.

Cheers

Martin


I used the "asm" keyword with the V1 version of CrossWorks but it no longer appears to work on V2. What should I do?

The asm keyword is a GNU C extension, the error is now occurring because CrossWorks V2 enables ANSI checking by default.

The solution is to either use the __asm__ keyword in place of the asm keyword or, alternatively, set the Compile > Enforce ANSI Checking project property to No to allow asm to work.