<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-27209140</id><updated>2011-08-31T19:22:16.381+08:00</updated><category term='Make'/><category term='Angel SWI'/><category term='debugging'/><category term='GNUARM'/><category term='Eclipse'/><category term='RVISS'/><category term='optimization'/><category term='Embedded OS'/><category term='MS Visual Studio'/><category term='ARM'/><category term='gcc'/><category term='testsuite'/><category term='ARMulator'/><category term='RVDS'/><category term='Apple'/><category term='Java'/><category term='newlib'/><title type='text'>Koda.Karma</title><subtitle type='html'>Scribbles from a reborn embedded software developer...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://koda-karma.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://koda-karma.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>myusri</name><uri>http://www.blogger.com/profile/10829992323167955133</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-27209140.post-482479330266967358</id><published>2007-04-03T19:08:00.000+08:00</published><updated>2007-04-05T20:11:36.033+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ARM'/><category scheme='http://www.blogger.com/atom/ns#' term='MS Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='RVISS'/><category scheme='http://www.blogger.com/atom/ns#' term='RVDS'/><title type='text'>Using Microsoft Visual C++ Express to compile RVISS model</title><content type='html'>One of the great things about RealView Instruction Set Simulator (RVISS/ARMulator) is that it supports creating device models. However, you would need to have Microsoft Visual C++ to compile the models. Thankfully, since 2005, Microsoft has offered a free version within its &lt;a href="http://msdn.microsoft.com/vstudio/express/downloads/"&gt;Microsoft Visual Studio Express Editions&lt;/a&gt;. (Of course, you need to eventually register to use it indefinitely and if I am not mistaken the registration requires you to run the dreaded "genuine system check".) It comes complete with a nice IDE. This is a far cry from what we would have got from Microsoft Visual C++ Toolkit 2003 long time back.&lt;br /&gt;&lt;br /&gt;The easiest thing is to use an existing device model from RVDS installation as a base and modify it from there. For example, let assume you want to use the timer model as a base. You should be able to locate file &lt;code&gt;timer.c&lt;/code&gt; and folder &lt;code&gt;timer.b&lt;/code&gt; in &lt;code&gt;RVARMulator\ExtensionKit\1.4.1\win-32-pentium\armulator&lt;/code&gt; in your RVDS installation folder. Make copy of each into &lt;code&gt;mytimer.c&lt;/code&gt; and &lt;code&gt;mytimer.b&lt;/code&gt;, respectively. You should be able to locate the &lt;code&gt;Makefile&lt;/code&gt; within the &lt;code&gt;mytimer.b&lt;/code&gt; folder. In the &lt;code&gt;Makefile&lt;/code&gt;, rename all '&lt;code&gt;timer&lt;/code&gt;' occurrences into '&lt;code&gt;mytimer&lt;/code&gt;' and '&lt;code&gt;Timer&lt;/code&gt;' into '&lt;code&gt;MyTimer&lt;/code&gt;' in the &lt;code&gt;Makefile&lt;/code&gt;. You could choose any other names you like for '&lt;code&gt;mytimer&lt;/code&gt;' and '&lt;code&gt;MyTimer&lt;/code&gt;', of course.&lt;br /&gt;&lt;br /&gt;The best way to compile the device model is to use the "Visual Studio 2005 Command Prompt" from the &lt;span style="font-style: italic;"&gt;Start menu &gt; All Programs &gt; Visual C++ 2005 Express Edition &gt; Visual Studio Tools&lt;/span&gt;. This custom command prompt sets up the appropriate environment variables to effectively use MSVC++ Express from the command line. If you prefer to configure your own environment variables, make sure you add &lt;i&gt;&amp;lt;install&amp;gt;&lt;/i&gt;&lt;code&gt;\VC\INCLUDE&lt;/code&gt; into &lt;code&gt;INCLUDE&lt;/code&gt;, &lt;i&gt;&amp;lt;install&amp;gt;&lt;/i&gt;&lt;code&gt;\VC\LIB&lt;/code&gt; and &lt;i&gt;&amp;lt;install&amp;gt;&lt;/i&gt;&lt;code&gt;\Common7\IDE;&lt;/code&gt;&lt;i&gt;&amp;lt;install&amp;gt;&lt;/i&gt;&lt;code&gt;\VC\BIN&lt;/code&gt; into &lt;code&gt;Path&lt;/code&gt;, where &lt;i&gt;&amp;lt;install&amp;gt;&lt;/i&gt; is where you have installed MSVC Express. In particular, if you forgot to include &lt;i&gt;&amp;lt;install&amp;gt;&lt;/i&gt;&lt;code&gt;\Common7\IDE;&lt;/code&gt;, you would get this when you issue &lt;code&gt;nmake&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;cl /c /Za /I..\.. /I..\..\..\armulif /I..\..\..\rdi&lt;br /&gt;   /I..\..\..\clx /D_CONSOLE /D_MBCS /DNLS /nologo&lt;br /&gt;   /W3 /GX /GR /WX -DRDI_VERSION=151 -DARM10MODEL&lt;br /&gt;   /O2 /G6 /MD /DNDEBUG&lt;br /&gt;   /DARM_RELEASE="\"RVARMulatorISS1.4.1\""&lt;br /&gt;   /DBUILD_NUMBER=290 /Iderived  /Fomytimer.obj&lt;br /&gt;   ..\..\mytimer.c&lt;br /&gt;NMAKE : fatal error U1077: '...\cl.EXE' : return&lt;br /&gt;   code '0xc0000135'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And if you explicitly issue the linking command above you would get an "&lt;code&gt;mspdb80.dll&lt;/code&gt; not found" error. So make sure &lt;i&gt;&amp;lt;install&amp;gt;&lt;/i&gt;&lt;code&gt;\Common7\IDE&lt;/code&gt; in your &lt;code&gt;Path&lt;/code&gt; environment variable.&lt;br /&gt;&lt;br /&gt;Once you have got the environment variables out of the way, when you issue &lt;code&gt;nmake&lt;/code&gt; you would still get a small error as shown below:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;..\..\..\armulif\perip_sordi.h(184) : error C2220:&lt;br /&gt;  warning treated as error - no 'object' file&lt;br /&gt;  generated&lt;br /&gt;..\..\..\armulif\perip_sordi.h(184) : warning C4996:&lt;br /&gt;  'sprintf': This function or variable may be unsafe.&lt;br /&gt;  Consider using sprintf_s instead. To disable&lt;br /&gt;  deprecation, use _CRT_SECURE_NO_WARNINGS. See&lt;br /&gt;  online help for details.&lt;br /&gt;D:\msvcx\VC\INCLUDE\stdio.h(345) : see declaration&lt;br /&gt;  of 'sprintf'&lt;br /&gt;NMAKE : fatal error U1077: '...\cl.EXE' : return&lt;br /&gt;  code '0x2'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ARM has chosen to treat every warning as error with option &lt;code&gt;/WX&lt;/code&gt;. Nobel, yes, but it is not future-proof. Apparently, with the latest Visual C++ &lt;code&gt;sprintf&lt;/code&gt; and other buffer clobbering functions that do not specify the buffer length would generate a warning. Removing the option from the &lt;code&gt;Makefile&lt;/code&gt; would do the trick.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27209140-482479330266967358?l=koda-karma.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://koda-karma.blogspot.com/feeds/482479330266967358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27209140&amp;postID=482479330266967358' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/482479330266967358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/482479330266967358'/><link rel='alternate' type='text/html' href='http://koda-karma.blogspot.com/2007/04/using-microsoft-visual-c-express-to.html' title='Using Microsoft Visual C++ Express to compile RVISS model'/><author><name>myusri</name><uri>http://www.blogger.com/profile/10829992323167955133</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27209140.post-4352860809162265614</id><published>2007-01-12T08:20:00.000+08:00</published><updated>2007-01-12T08:57:22.991+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Apple'/><category scheme='http://www.blogger.com/atom/ns#' term='Embedded OS'/><title type='text'>Mac OS X Embedded?</title><content type='html'>&lt;a href="http://www.apple.com/iphone/"&gt;Apple &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;iPhone&lt;/span&gt;&lt;/a&gt; has been revealed recently and it gets me all excited. The phone itself is nice but I am more interested in the OS behind it. It is none other than the Mac OS X itself. What processor it is running on, by the way?&lt;br /&gt;&lt;br /&gt;I'm wondering whether this "embedded" OS X would be available to us, embedded developers, to tinker with. Knowing Apple, however, I don't think this would happen. Maybe, it is a good thing. I haven't bought anything from Apple Inc. yet. I would love to have the &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;MacBook&lt;/span&gt; with Intel Core Duo but my wife won't let me. Anyway, with Apple products, they tend to be very consistent. You know what to expect. So embedded &lt;a href="http://www.applematters.com/index.php/section/comments/opendarwin-dies-a-lonely-death/"&gt;Darwin OS&lt;/a&gt;, anyone?&lt;br /&gt;&lt;br /&gt;Now, on the &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;iPhone&lt;/span&gt; product itself, why only EDGE? Why not 3G? Also, why it would only be available in 2008 for us in Asia? We can't wait that long. And please support a 'virtual' 12-button keypad. I know I am a dinosaur but I am used to it and from, the look of it, the virtual QWERTY keyboard buttons are too small for my fingers.&lt;br /&gt;&lt;br /&gt;Let the new age in personal mobility begin!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27209140-4352860809162265614?l=koda-karma.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://koda-karma.blogspot.com/feeds/4352860809162265614/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27209140&amp;postID=4352860809162265614' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/4352860809162265614'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/4352860809162265614'/><link rel='alternate' type='text/html' href='http://koda-karma.blogspot.com/2007/01/mac-os-x-embedded.html' title='Mac OS X Embedded?'/><author><name>myusri</name><uri>http://www.blogger.com/profile/10829992323167955133</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27209140.post-6306491730262034142</id><published>2007-01-11T08:22:00.000+08:00</published><updated>2007-01-12T16:26:56.454+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ARM'/><category scheme='http://www.blogger.com/atom/ns#' term='ARMulator'/><category scheme='http://www.blogger.com/atom/ns#' term='GNUARM'/><category scheme='http://www.blogger.com/atom/ns#' term='RVDS'/><title type='text'>RVDS ARMulator and GNUARM-compiled binaries</title><content type='html'>I have started to use the ARMulator , which is also called the RealView Instruction Set Simulator (RVISS). I was interested to see if the binaries compiled using the GNUARM toolchain could work with the ARMulator. Specifically, I was hoping that the input/output (from &lt;code&gt;printf&lt;/code&gt; or &lt;code&gt;fgets&lt;/code&gt;, for example) could be done from within the RealView Debugger (RVD) session itself. To my surprise, the GNUARM-compiled binaries would not show &lt;code&gt;printf&lt;/code&gt; output when ran using the RVD/ARMulator even though they worked just fine with GDB. I have customized my &lt;code&gt;crt0.S&lt;/code&gt;, so that was the first place I looked. In addition, writing a simple code using &lt;code&gt;printf&lt;/code&gt; and &lt;code&gt;fgets&lt;/code&gt; and compiling it using GNUARM without using my custom &lt;code&gt;crt0.S&lt;/code&gt; seemed to work. Lo and behold, after comparing my &lt;code&gt;crt0.S&lt;/code&gt; and the default one within the GNUARM distribution, I found that I had failed to call &lt;code&gt;initialise_monitor_handles&lt;/code&gt; in my &lt;code&gt;crt0.S&lt;/code&gt;. Doing this after stack initialization and BSS clearing fixed the problem.&lt;br /&gt;&lt;br /&gt;(Apparently, the problem above only appears in GNUARM toolchain from &lt;a href="http://www.gnuarm.org/"&gt;gnuarm.org&lt;/a&gt;. The toolchain from &lt;a href="http://www.codesourcery.com/"&gt;CodeSourcery&lt;/a&gt; does not exhibit this problem. In fact, the latter does not even have the &lt;code&gt;initialise_monitor_handles&lt;/code&gt; function. Oh, well.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27209140-6306491730262034142?l=koda-karma.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://koda-karma.blogspot.com/feeds/6306491730262034142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27209140&amp;postID=6306491730262034142' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/6306491730262034142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/6306491730262034142'/><link rel='alternate' type='text/html' href='http://koda-karma.blogspot.com/2007/01/rvds-armulator-and-gnuarm-compiled.html' title='RVDS ARMulator and GNUARM-compiled binaries'/><author><name>myusri</name><uri>http://www.blogger.com/profile/10829992323167955133</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27209140.post-2232485362263536494</id><published>2007-01-09T08:07:00.000+08:00</published><updated>2007-01-09T08:59:08.390+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ARM'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='RVDS'/><title type='text'>RealView Development Suite and Eclipse</title><content type='html'>I am starting to use RVDS from ARM. I'm using it mainly for its debugger (RVD) and its simulator (RVISS). I don't know if I will ever use the CodeWarrior IDE that comes with it. However, since ARM supports a number of Eclipse plugins for RVDS, and I have been using Eclipse for most of my embedded work, I thought I would give the plugins a try.&lt;br /&gt;&lt;br /&gt;Download the Eclipse plugins and documentation from the &lt;a href="http://www.arm.com/support/downloads/info/12746.html"&gt;ARM website&lt;/a&gt;. Even though the &lt;a href="http://www.arm.com/eclipse/index.html"&gt;RVDS Eclipse plugins page&lt;/a&gt; mentions only Eclipse 3.1 and CDT 3.0.0, they work just fine with Eclipse 3.2 and CDT 3.1.0 I am using.&lt;br /&gt;&lt;br /&gt;To install the plugins, simply follow the instructions in the &lt;a href="http://www.arm.com/pdfs/ARMDUI0330Af.pdf"&gt;RVDS Eclipse Plugins User Guide&lt;/a&gt;. Once installed, you can start creating your first RVDS "Hello World!" program in Eclipse. Alternatively, follow the User Guide to create an ARM or ARM/Thumb interworking project.&lt;br /&gt;&lt;br /&gt;The User Guide also mentions that GNU Make is required and we should be able to use either the one from Cygwin or from MinGW. I find, however, that if you use Cygwin Make, the first build of a project will succeed but subsequent builds will fail with this error:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;hello-rvds.d:6: *** target pattern contains no `%'.  Stop.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Or something to that effect. It has something to do with the Cygwin Make program inability to understand Windows full pathname which includes the drive letter followed by a colon. So, your only option is to download the &lt;a href="http://prdownloads.sf.net/mingw/mingw32-make-3.80.0-3.exe?download"&gt;GNU Make from MinGW&lt;/a&gt;. It is an installer. Once installed, put the path to the Make program in your PATH environment variable. Since the program is named &lt;code&gt;mingw32-make.exe&lt;/code&gt;, which is different from the one for Cygwin, you do not have to worry about name clash.&lt;br /&gt;&lt;br /&gt;One last detail, you also need to replace the default &lt;code&gt;make&lt;/code&gt; with &lt;code&gt;mingw32-make&lt;/code&gt; in your project properties &gt; C/C++ Build &gt; Build Settings as shown below:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_cDszbYamgLg/RaLnp9sBieI/AAAAAAAAAAM/3CzgDIvGrpc/s1600-h/rvds-eclipse.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_cDszbYamgLg/RaLnp9sBieI/AAAAAAAAAAM/3CzgDIvGrpc/s320/rvds-eclipse.jpg" alt="" id="BLOGGER_PHOTO_ID_5017827642964019682" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27209140-2232485362263536494?l=koda-karma.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://koda-karma.blogspot.com/feeds/2232485362263536494/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27209140&amp;postID=2232485362263536494' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/2232485362263536494'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/2232485362263536494'/><link rel='alternate' type='text/html' href='http://koda-karma.blogspot.com/2007/01/realview-development-suite-and-eclipse.html' title='RealView Development Suite and Eclipse'/><author><name>myusri</name><uri>http://www.blogger.com/profile/10829992323167955133</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_cDszbYamgLg/RaLnp9sBieI/AAAAAAAAAAM/3CzgDIvGrpc/s72-c/rvds-eclipse.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27209140.post-115719904890541942</id><published>2006-09-02T19:17:00.000+08:00</published><updated>2007-01-08T23:01:37.641+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ARM'/><category scheme='http://www.blogger.com/atom/ns#' term='gcc'/><category scheme='http://www.blogger.com/atom/ns#' term='optimization'/><title type='text'>A case of premature optimization</title><content type='html'>I had a case of premature optimization recently. I need to learn more self-control: to take it easy and let the compiler does what it does best.&lt;br /&gt;&lt;br /&gt;I had a few tests I needed to write and they had to be super tight because they would run in gate level simulation (GLS) where time is a luxury the verification team do not have.&lt;br /&gt;&lt;br /&gt;My other more normal test programs make use of the newlib library and I have implemented system clock and console to make writing test programs more palatable. However adding newlib makes test programs big and slow to complete in a simulation environment. So, for the GLS, I decided to make the test programs as lean as possible. This means not using newlib, or any of the libraries for that matter. Which also means no standard C library and the math emulation (because ARM7 do not have math coprocessor and does not have divide instruction.)&lt;br /&gt;&lt;br /&gt;As an alternative to using &lt;code&gt;printf&lt;/code&gt; and friends, I wrote a function to write to a GPIO port instead:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;static void lean_vout(char *s, ...) {&lt;br /&gt; va_list ap;&lt;br /&gt; va_start(ap, s);&lt;br /&gt; lean_out(s);&lt;br /&gt; while ( (s=va_arg(ap,char*)) != 0 )&lt;br /&gt;   lean_out(s);&lt;br /&gt; va_end(ap);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Where &lt;code&gt;lean_out&lt;/code&gt; prints each character in the string to the GPIO port. Printing to GPIO is fast and the verification team can easily see the characters in the simulation signal viewer.&lt;br /&gt;&lt;br /&gt;Beside, the ability to see what is happening in a test program, the ability to do assertions is important too. I cannot use the facility in the &lt;code&gt;&amp;lt;assert.h&amp;gt;&lt;/code&gt; because it makes use of &lt;code&gt;printf&lt;/code&gt;. So, I have this macro for my lean-and-mean assertion:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#define lean_assert(cond) if (!(cond)) lean_do_assert(__FILE__, __LINE__);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Basically, when the assertion fails, the filename and the line number would scuttle through the GPIO port. But there is a small problem: I need to convert the line number into its ASCII representation. Because, recently, I had a program failing to compile because I use division with &lt;code&gt;-nostdlib&lt;/code&gt;, I thought I needed to use an algorithm to divide by 10 without actually using the division operator. And find I did: &lt;a href="http://www.hackersdelight.org/divcMore.pdf"&gt;Section 10 to the "Hacker's Delight"&lt;/a&gt; book which talks about division by constant in great depth. Based on the information in this section, I came up with my version of &lt;code&gt;itoa&lt;/code&gt; for converting integer to base-10 ASCII representation:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/* taken straight from "Hacker's Delight" */&lt;br /&gt;&lt;br /&gt;static int remu10(unsigned n) {&lt;br /&gt; static char table[16] =&lt;br /&gt;   {0, 1, 2, 2, 3, 3, 4, 5,&lt;br /&gt;    5, 6, 7, 7, 8, 8, 9, 0};&lt;br /&gt; n = (0x19999999*n + (n &amp;gt;&amp;gt; 1) + (n &amp;gt;&amp;gt; 3)) &amp;gt;&amp;gt; 28;&lt;br /&gt; return table[n];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;char *lean_itoa(int n, char *s, int len) {&lt;br /&gt; int r;&lt;br /&gt; s += len;&lt;br /&gt; *--s = '\0';&lt;br /&gt; while (n &amp;&amp;amp; len &amp;gt; 0) {&lt;br /&gt;   r = remu10(n);&lt;br /&gt;   n = ((n - r) &amp;gt;&amp;gt; 1)*0xCCCCCCCD; /* also from "Hacker's Delight" */&lt;br /&gt;   *--s = '0' + r;&lt;br /&gt;   --len;&lt;br /&gt; }&lt;br /&gt; return s;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Basically, the remainder is computed and the divide-by-10 is done using the remainder. The generated code from &lt;code&gt;arm-elf-gcc&lt;/code&gt; (with optimization &lt;code&gt;-O2&lt;/code&gt;):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;0000820c &amp;lt;lean_itoa&amp;gt;:&lt;br /&gt;   820c: e0821001  add r1, r2, r1&lt;br /&gt;   8210: e3a03000  mov r3, #0 ; 0x0&lt;br /&gt;   8214: e3500000  cmp r0, #0 ; 0x0&lt;br /&gt;   8218: 13520000  cmpne r2, #0 ; 0x0&lt;br /&gt;   821c: e92d4010  stmdb sp!, {r4, lr}&lt;br /&gt;   8220: e1a0c002  mov ip, r2&lt;br /&gt;   8224: e5413001  strb r3, [r1, #-1]&lt;br /&gt;   8228: e2411001  sub r1, r1, #1 ; 0x1&lt;br /&gt;   822c: da000018  ble 8294 &amp;lt;lean_itoa+0x88&amp;gt;&lt;br /&gt;   8230: e59f4064  ldr r4, [pc, #100] ; 829c &amp;lt;.text+0x27c&amp;gt;&lt;br /&gt;   8234: e1a0e001  mov lr, r1&lt;br /&gt;   8238: e0803080  add r3, r0, r0, lsl #1&lt;br /&gt;   823c: e0803103  add r3, r0, r3, lsl #2&lt;br /&gt;   8240: e0633303  rsb r3, r3, r3, lsl #6&lt;br /&gt;   8244: e0803103  add r3, r0, r3, lsl #2&lt;br /&gt;   8248: e0633703  rsb r3, r3, r3, lsl #14&lt;br /&gt;   824c: e0803183  add r3, r0, r3, lsl #3&lt;br /&gt;   8250: e08330a0  add r3, r3, r0, lsr #1&lt;br /&gt;   8254: e08331a0  add r3, r3, r0, lsr #3&lt;br /&gt;   8258: e7d41e23  ldrb r1, [r4, r3, lsr #28]&lt;br /&gt;   825c: e0612000  rsb r2, r1, r0&lt;br /&gt;   8260: e1a020c2  mov r2, r2, asr #1&lt;br /&gt;   8264: e0823082  add r3, r2, r2, lsl #1&lt;br /&gt;   8268: e0833203  add r3, r3, r3, lsl #4&lt;br /&gt;   826c: e0833403  add r3, r3, r3, lsl #8&lt;br /&gt;   8270: e0833803  add r3, r3, r3, lsl #16&lt;br /&gt;   8274: e0820103  add r0, r2, r3, lsl #2&lt;br /&gt;   8278: e24cc001  sub ip, ip, #1 ; 0x1&lt;br /&gt;   827c: e2811030  add r1, r1, #48 ; 0x30&lt;br /&gt;   8280: e3500000  cmp r0, #0 ; 0x0&lt;br /&gt;   8284: 135c0000  cmpne ip, #0 ; 0x0&lt;br /&gt;   8288: e56e1001  strb r1, [lr, #-1]!&lt;br /&gt;   828c: caffffe9  bgt 8238 &amp;lt;lean_itoa+0x2c&amp;gt;&lt;br /&gt;   8290: e1a0100e  mov r1, lr&lt;br /&gt;   8294: e1a00001  mov r0, r1&lt;br /&gt;   8298: e8bd8010  ldmia sp!, {r4, pc}&lt;br /&gt;   829c: 0001085b  andeq r0, r1, fp, asr r8&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;From the look of it, the compiler has tried very hard to use additions and shifts to perform the constant multiplications. This led me into thinking that, maybe, the compiler would be clever enough to avoid doing division in division by constants (of course, it is but it didn't occur to my thick head.) I tried this instead:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;char *lean_itoa(int n, char *s, int len) {&lt;br /&gt; int r;&lt;br /&gt; s += len;&lt;br /&gt; *--s = '\0';&lt;br /&gt; while (n &amp;&amp;amp; len &amp;gt; 0) {&lt;br /&gt;   r = n % 10;&lt;br /&gt;   n = n / 10;&lt;br /&gt;   *--s = '0' + r;&lt;br /&gt;   --len;&lt;br /&gt; }&lt;br /&gt; return s;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And the generated assembly code:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;0000820c &amp;lt;lean_itoa&amp;gt;:&lt;br /&gt;   820c: e0821001  add r1, r2, r1&lt;br /&gt;   8210: e3a03000  mov r3, #0 ; 0x0&lt;br /&gt;   8214: e3500000  cmp r0, #0 ; 0x0&lt;br /&gt;   8218: 13520000  cmpne r2, #0 ; 0x0&lt;br /&gt;   821c: e92d4010  stmdb sp!, {r4, lr}&lt;br /&gt;   8220: e5413001  strb r3, [r1, #-1]&lt;br /&gt;   8224: e1a0e002  mov lr, r2&lt;br /&gt;   8228: e2411001  sub r1, r1, #1 ; 0x1&lt;br /&gt;   822c: da00000f  ble 8270 &amp;lt;lean_itoa+0x64&amp;gt;&lt;br /&gt;   8230: e59f4040  ldr r4, [pc, #64] ; 8278 &amp;lt;.text+0x258&amp;gt;&lt;br /&gt;   8234: e1a0c001  mov ip, r1&lt;br /&gt;   8238: e0c13094  smull r3, r1, r4, r0&lt;br /&gt;   823c: e1a03fc0  mov r3, r0, asr #31&lt;br /&gt;   8240: e0633141  rsb r3, r3, r1, asr #2&lt;br /&gt;   8244: e1a02003  mov r2, r3&lt;br /&gt;   8248: e0833103  add r3, r3, r3, lsl #2&lt;br /&gt;   824c: e0403083  sub r3, r0, r3, lsl #1&lt;br /&gt;   8250: e24ee001  sub lr, lr, #1 ; 0x1&lt;br /&gt;   8254: e2833030  add r3, r3, #48 ; 0x30&lt;br /&gt;   8258: e3520000  cmp r2, #0 ; 0x0&lt;br /&gt;   825c: 135e0000  cmpne lr, #0 ; 0x0&lt;br /&gt;   8260: e1a00002  mov r0, r2&lt;br /&gt;   8264: e56c3001  strb r3, [ip, #-1]!&lt;br /&gt;   8268: cafffff2  bgt 8238 &amp;lt;lean_itoa+0x2c&amp;gt;&lt;br /&gt;   826c: e1a0100c  mov r1, ip&lt;br /&gt;   8270: e1a00001  mov r0, r1&lt;br /&gt;   8274: e8bd8010  ldmia sp!, {r4, pc}&lt;br /&gt;   8278: 66666667  strvsbt r6, [r6], -r7, ror #12&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So, yes! The compiler avoids calling the division function. The previous generated code has 36 instructions with one load instruction for the table. The second one has 27 instructions with one load instruction used in the "signed multiply long" instruction. Which one is faster? I presume the compiler concluded that using the long multiplication is faster than additions-and-shifts (See also &lt;a href="http://sources.redhat.com/ml/crossgcc/2000-08/msg00109.html"&gt;Re: Optimization question&lt;/a&gt;). But surely the second code is more compact.&lt;br /&gt;&lt;br /&gt;This led me into digging further on how long divide-by-constant optimization has been around in GCC. Apparently, since 1994 when Torbjorn Granlund and Peter L. Montgomery wrote about it in their paper, "&lt;a href="http://swox.se/%7Etg/divcnst-pldi94.pdf"&gt;Division by Invariant Integers using Multiplication&lt;/a&gt;."&lt;br /&gt;&lt;br /&gt;So there you have it. A case of trying to hard. I should've let GCC do its job. But I have learned a lot from the whole process.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27209140-115719904890541942?l=koda-karma.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://koda-karma.blogspot.com/feeds/115719904890541942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27209140&amp;postID=115719904890541942' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/115719904890541942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/115719904890541942'/><link rel='alternate' type='text/html' href='http://koda-karma.blogspot.com/2006/09/case-of-premature-optimization.html' title='A case of premature optimization'/><author><name>myusri</name><uri>http://www.blogger.com/profile/10829992323167955133</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27209140.post-115555795233854967</id><published>2006-08-14T20:04:00.000+08:00</published><updated>2007-01-08T23:13:20.889+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testsuite'/><category scheme='http://www.blogger.com/atom/ns#' term='Make'/><title type='text'>Recursive Make Considered Harmful -- Building Multiple Programs</title><content type='html'>I have a number of test programs in a testsuite for an embedded system. They may share source files among them in addition to some other common files. I do not feel like managing a number of full-blown makefiles in building these programs. Besides, &lt;a href="http://www.canb.auug.org.au/~millerp/"&gt;Peter Miller&lt;/a&gt; has written a very excellent paper on "&lt;a href="http://www.pcug.org.au/~millerp/rmch/recu-make-cons-harm.html"&gt;Recursive Make Considered Harmful&lt;/a&gt;". He argued that multiple makefiles with common dependencies simply do not work.&lt;br /&gt;&lt;br /&gt;The paper above shows how to handle building a program with dependencies that come from multiple directories. How would we then build multiple programs using a single makefile without too much boilerplate cut-and-paste? The latest GNU make 3.81 with (correct) &lt;code&gt;eval&lt;/code&gt; support makes this very easy. Just like in the paper, I depend on GCC to generate source code dependencies and also on &lt;code&gt;sed&lt;/code&gt;, the stream editor, to transform the dependency output to what I want. But first, below is the structure of my build directory:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/4242/2858/1600/build-dir.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/4242/2858/400/build-dir.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;build&lt;/code&gt; directory contains the makefile and the other directories are "module" directories.&lt;br /&gt;&lt;br /&gt;Similar to the paper, I put makefile include file &lt;code&gt;module.mk&lt;/code&gt; in each module directory. The source files other modules may depend on are exported through the &lt;code&gt;SRC&lt;/code&gt; variable. For my case, however, a module may also have one or more source files that contribute to the implementation of the &lt;code&gt;main&lt;/code&gt; function for the module (let's call this module &lt;i&gt;program module&lt;/i&gt;.) For this purpose, I define &lt;code&gt;PROG_SRC&lt;/code&gt; variable for declaring these source files. An example from &lt;code&gt;module.mk&lt;/code&gt; from my &lt;code&gt;dhrystone&lt;/code&gt; module is given below.&lt;br /&gt;&lt;pre&gt;SRC +=&lt;br /&gt;PROG_SRC := dhrystone/dhry_1.c dhrystone/dhry_2.c&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Below is another example of &lt;code&gt;module.mk&lt;/code&gt; from my &lt;code&gt;common&lt;/code&gt; module, which do not have a &lt;code&gt;main&lt;/code&gt; function.&lt;br /&gt;&lt;pre&gt;SRC += common/vec.S common/swi.S common/crt0.S \ &lt;br /&gt;       common/int-handler.c common/swi-handler.c \ &lt;br /&gt;       common/intr-write.c common/swi-write.c \ &lt;br /&gt;       common/swi-clock.c common/console.c&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In my singular makefile, I have variable &lt;code&gt;PROGS&lt;/code&gt; to declare all program modules and &lt;code&gt;COMMS&lt;/code&gt; for other "common" modules. For example:&lt;br /&gt;&lt;pre&gt;PROGS := simple unmapped rap fiq dhrystone large&lt;br /&gt;COMMS := common&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To declare the modules a program module depends on, I declare makefile variable with name like &lt;code&gt;&lt;i&gt;&amp;lt;program-module&amp;gt;&lt;/i&gt;_MK&lt;/code&gt;. Basically, this variable lists the &lt;code&gt;module.mk&lt;/code&gt; files from the modules the program module depends on. An example is given below for my &lt;code&gt;simple&lt;/code&gt; program module:&lt;br /&gt;&lt;pre&gt;simple_MK := ../common/module.mk ../simple/module.mk&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The above simply says that the &lt;code&gt;simple&lt;/code&gt; module depends on the &lt;code&gt;common&lt;/code&gt; module and its own. Note that the "self" &lt;code&gt;module.mk&lt;/code&gt; must be last in the list so that its &lt;code&gt;PROG_SRC&lt;/code&gt; variable will take effect.&lt;br /&gt;&lt;br /&gt;Given that we have defined all of the program modules and the &lt;code&gt;module.mk&lt;/code&gt; files each depends on, how do we go about creating the rules for building the program modules? Copy-and-paste is one option but where is the fun in that? What we need is rule building template which can be "instantiated" through &lt;code&gt;eval&lt;/code&gt; magic. The template is given below:&lt;br /&gt;&lt;pre&gt;define PROG_template&lt;br /&gt;SRC :=&lt;br /&gt;include $$($(1)_MK)&lt;br /&gt;$(1)_OBJ := $$(call get_objs,$$(patsubst %, ../%,$$(PROG_SRC) $$(SRC)))&lt;br /&gt;&lt;br /&gt;$(1): $$($(1)_OBJ)&lt;br /&gt;        $$(CC) $$(LDFLAGS) -o $$@ $$^&lt;br /&gt;endef&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So if you were to call &lt;code&gt;PROG_template&lt;/code&gt; with argument &lt;code&gt;simple&lt;/code&gt;, &lt;code&gt;make&lt;/code&gt; would have emitted this text:&lt;br /&gt;&lt;pre&gt;SRC :=&lt;br /&gt;include $(simple_MK)&lt;br /&gt;simple_OBJ := ../simple/simple.o ../common/vec.S # ...and other common files&lt;br /&gt;&lt;br /&gt;simple: $(simple_OBJ)&lt;br /&gt;        $(CC) $(LDFLAGS) -o $@ $^&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;All &lt;code&gt;module.mk&lt;/code&gt; files &lt;code&gt;simple&lt;/code&gt; depends on are first included, thus filling in the &lt;code&gt;SRC&lt;/code&gt; and &lt;code&gt;PROG_SRC&lt;/code&gt; variables. Next, the object files it depends on are listed followed by the rule to build &lt;code&gt;simple&lt;/code&gt;. By the way, function &lt;code&gt;get_objs&lt;/code&gt; called above converts all &lt;code&gt;.c&lt;/code&gt; and &lt;code&gt;.S&lt;/code&gt; filenames into &lt;code&gt;.o&lt;/code&gt; filenames:&lt;br /&gt;&lt;pre&gt;define get_objs&lt;br /&gt; $(patsubst %.S,%.o,  $(filter %.S,$(1)))  $(patsubst %.c,%.o,  $(filter %.c,$(1)))&lt;br /&gt;endef&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, the trick is to "evaluate" the emitted text for all of the program modules:&lt;br /&gt;&lt;pre&gt;$(foreach t,$(PROGS),$(eval $(call PROG_template,$(t))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And finally, one rule to build all program modules:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;progs: $(PROGS)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That is all there is to it. Below is the complete makefile for your reference.&lt;br /&gt;&lt;pre&gt;.SUFFIXES:&lt;br /&gt;.SUFFIXES: .h .c .S .o .lst .sym .d&lt;br /&gt;&lt;br /&gt;# list the test program to build. There should be a directory for each&lt;br /&gt;# test program with the same name. COMMS are for directories that contains&lt;br /&gt;# common source files but do not contain main function.&lt;br /&gt;&lt;br /&gt;PROGS := simple unmapped rap fiq dhrystone large&lt;br /&gt;COMMS := common&lt;br /&gt;&lt;br /&gt;# define the module.mk files to include for building each test. Each&lt;br /&gt;# module.mk defines the source files it exports in variable SRC and,&lt;br /&gt;# if the module defines a program, the program source file(s) in&lt;br /&gt;# PROG_SRC. Put the module.mk for the program last.&lt;br /&gt;&lt;br /&gt;simple_MK := ../common/module.mk ../simple/module.mk&lt;br /&gt;unmapped_MK := ../common/module.mk ../unmapped/module.mk&lt;br /&gt;rap_MK := ../common/module.mk ../rap/module.mk&lt;br /&gt;fiq_MK := ../common/module.mk ../fiq/module.mk&lt;br /&gt;dhrystone_MK := ../common/module.mk ../dhrystone/module.mk&lt;br /&gt;large_MK := ../common/module.mk ../large/module.mk&lt;br /&gt;&lt;br /&gt;# !!!DO NOT CHANGE ANYTHING BELOW THIS LINE!!!&lt;br /&gt;&lt;br /&gt;TARGET:=arm-elf&lt;br /&gt;CC:=$(TARGET)-gcc&lt;br /&gt;AS:=$(TARGET)-as&lt;br /&gt;LD:=$(TARGET)-ld&lt;br /&gt;OBJDUMP:=$(TARGET)-objdump&lt;br /&gt;NM:=$(TARGET)-nm&lt;br /&gt;OBJCOPY:=$(TARGET)-objcopy&lt;br /&gt;STRIP:=$(TARGET)-strip&lt;br /&gt;RM:=rm&lt;br /&gt;&lt;br /&gt;SED:=sed&lt;br /&gt;LDSCRIPT:=zero.ld&lt;br /&gt;&lt;br /&gt;XDEFINES:=-DHZ=100&lt;br /&gt;XINCLUDES:=$(COMMS:%=-I../%) $(PROGS:%=-I../%)&lt;br /&gt;DFLAGS:=-g&lt;br /&gt;OFLAGS:=-O2 -fomit-frame-pointer&lt;br /&gt;WFLAGS:=-ansi -Wall -Wstrict-prototypes -Wno-trigraphs&lt;br /&gt;CFLAGS:=-mcpu=arm7tdmi $(DFLAGS) $(OFLAGS) $(WFLAGS) \ &lt;br /&gt;         $(XDEFINES) $(DEFINES) $(XINCLUDES) $(INCLUDES)&lt;br /&gt;ASFLAGS := $(SDDEFINES) $(XDEFINES) $(DEFINES) $(XINCLUDES) $(INCLUDES)&lt;br /&gt;LDFLAGS := $(CFLAGS) -Wl,--script=$(LDSCRIPT) -nostartfiles&lt;br /&gt;&lt;br /&gt;#objdump flags for generating listing files&lt;br /&gt;ODFLAGS :=&lt;br /&gt;&lt;br /&gt;.PHONY: all progs listings clean clean-dep clean-all&lt;br /&gt;&lt;br /&gt;all: progs listings&lt;br /&gt;&lt;br /&gt;progs: $(PROGS)&lt;br /&gt;&lt;br /&gt;listings: $(PROGS:%=%.lst) $(PROGS:%=%.sym)&lt;br /&gt;&lt;br /&gt;# deduce object files from .S and .c files&lt;br /&gt;&lt;br /&gt;define get_objs&lt;br /&gt; $(patsubst %.S,%.o, $(filter %.S,$(1))) $(patsubst %.c,%.o, $(filter %.c,$(1)))&lt;br /&gt;endef&lt;br /&gt;&lt;br /&gt;# an eval template for deducing object files and rule for a program.&lt;br /&gt;# $(1) is the test program name.&lt;br /&gt;&lt;br /&gt;define PROG_template&lt;br /&gt;SRC :=&lt;br /&gt;include $$($(1)_MK)&lt;br /&gt;$(1)_OBJ := $$(call get_objs,$$(patsubst %, ../%,$$(PROG_SRC) $$(SRC)))&lt;br /&gt;&lt;br /&gt;$(1): $$($(1)_OBJ)&lt;br /&gt; $$(CC) $$(LDFLAGS) -o $$@ $$^&lt;br /&gt;endef&lt;br /&gt;&lt;br /&gt;# generate the rule for building each of the programs&lt;br /&gt;&lt;br /&gt;$(foreach t,$(PROGS),$(eval $(call PROG_template,$(t))))&lt;br /&gt;&lt;br /&gt;# generate all of the object files from all test test programs&lt;br /&gt;# and use it to include all of the dependency files.&lt;br /&gt;&lt;br /&gt;ALL_OBJ :=&lt;br /&gt;$(foreach t,$(PROGS),$(eval ALL_OBJ += $$($(t)_OBJ)))&lt;br /&gt;ALL_OBJ := $(sort $(ALL_OBJ))&lt;br /&gt;&lt;br /&gt;include $(ALL_OBJ:.o=.d)&lt;br /&gt;&lt;br /&gt;clean:&lt;br /&gt;        -$(RM) $(PROGS) $(PROGS:%=%.lst) $(PROGS:%=%.sym) \ &lt;br /&gt;               $(ALL_OBJ)&lt;br /&gt;&lt;br /&gt;clean-dep:&lt;br /&gt;        -$(RM) $(ALL_OBJ:.o=.d)&lt;br /&gt;&lt;br /&gt;clean-all: clean clean-dep&lt;br /&gt;&lt;br /&gt;%.lst: %&lt;br /&gt;        $(OBJDUMP) $(ODFLAGS) -d $&lt; &gt; $@&lt;br /&gt;&lt;br /&gt;%.sym: %&lt;br /&gt;        $(NM) -n $&lt; &gt; $@&lt;br /&gt;&lt;br /&gt;%.d: %.c&lt;br /&gt;        @echo generating dependencies from $&lt;&lt;br /&gt;        @$(CC) $(CFLAGS) -MM -MG $&lt; | \ &lt;br /&gt;        $(SED) 's%^\(.*\)\.o%$(dir $@)\1.d $(dir $@)\1.o%' &gt; $@&lt;br /&gt;&lt;br /&gt;%.d: %.S&lt;br /&gt;        @echo generating dependencies from $&lt;&lt;br /&gt;        @$(CC) $(ASFLAGS) -MM -MG $&lt; | \ &lt;br /&gt;        $(SED) 's%^\(.*\)\.o%$(dir $@)\1.d $(dir $@)\1.o%' &gt; $@&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;(Note: You need to change the space characters before each command in a rule with a tab!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27209140-115555795233854967?l=koda-karma.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://koda-karma.blogspot.com/feeds/115555795233854967/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27209140&amp;postID=115555795233854967' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/115555795233854967'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/115555795233854967'/><link rel='alternate' type='text/html' href='http://koda-karma.blogspot.com/2006/08/recursive-make-considered-harmful.html' title='Recursive Make Considered Harmful -- Building Multiple Programs'/><author><name>myusri</name><uri>http://www.blogger.com/profile/10829992323167955133</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27209140.post-115258116353751992</id><published>2006-07-11T08:51:00.000+08:00</published><updated>2006-07-11T23:09:17.230+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='newlib'/><category scheme='http://www.blogger.com/atom/ns#' term='Angel SWI'/><title type='text'>Newlib Angel SWI handing in C</title><content type='html'>&lt;a href="http://koda-karma.blogspot.com/2006/05/newlib-printf-through-uart-on-gnu-arm.html"&gt;Previously&lt;/a&gt;, I have shown how to implement Angel SWI write command so that &lt;code&gt;printf&lt;/code&gt; and friends would work on a UART. That implementation was rather simplistic because the UART writing loop will hold the caller from doing any other useful stuff. What I want to do now is to make use of FIFO in the UART and also interrupt it only when the FIFO is empty enough.&lt;br /&gt;&lt;br /&gt;But first, I want to change the SWI handling from using ARM assembly code into C because the implementation now has become more sophisticated. Before you continue reading, I think you should also check &lt;a href="http://groups.yahoo.com/group/gnuarm/message/2333"&gt;the thread&lt;/a&gt; I started in the GNUARM mailing list on this subject where there were a lot of insights that can be gathered from the contributors to the thread.&lt;br /&gt;&lt;br /&gt;It seems like GCC supports C function that can act as the handler to the various exceptions that ARM can throw through the &lt;code&gt;__attribute__&lt;/code&gt; modifier. Below is an example of a SWI handler that would accept an Angel SWI call from newlib and see if it is a write command and write the bytes in the string to a specific location.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;static int *out = (int *) 0x08000000;&lt;br /&gt;&lt;br /&gt;int __attribute__((interrupt("SWI")))&lt;br /&gt; handle_swi(int reason, void *args) {&lt;br /&gt;&lt;br /&gt; int i, n, *a;&lt;br /&gt; char *s;&lt;br /&gt; if (reason != 5) return -1;&lt;br /&gt; a = (int*) args;&lt;br /&gt; s = (char *) a[1];&lt;br /&gt; n = a[2];&lt;br /&gt; for (i=0; i&amp;lt;n; ++i) *out = s[i];&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that for Angel SWI write to work, we need to return the number of bytes yet to be written. So zero is returned above because the function has written out all of the bytes. Now, if we link this function to the ARM vector address for SWI, it looks like it may work. But look closely at the generated assembly code for the function:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;00000000 &amp;lt;handle_swi&amp;gt;:&lt;br /&gt;  0:  cmp   r0, #5 ; 0x5&lt;br /&gt;  4:  stmdb sp!, {r0, r1, r2, r3, ip}&lt;br /&gt;  8:  mvnne r0, #0 ; 0x0&lt;br /&gt;  c:  beq   18 &amp;lt;handle_swi+0x18&amp;gt;&lt;br /&gt; 10:  ldmia sp!, {r0, r1, r2, r3, ip}&lt;br /&gt; 14:  movs  pc, lr&lt;br /&gt; 18:  ldr   r0, [r1, #8]&lt;br /&gt; 1c:  cmp   r0, #0 ; 0x0&lt;br /&gt; 20:  ldr   r1, [r1, #4]&lt;br /&gt; 24:  ble   44 &amp;lt;handle_swi+0x44&amp;gt;&lt;br /&gt; 28:  mov   r2, #0 ; 0x0&lt;br /&gt; 2c:  mov   ip, #134217728 ; 0x8000000&lt;br /&gt; 30:  ldrb  r3, [r2, r1]&lt;br /&gt; 34:  add   r2, r2, #1 ; 0x1&lt;br /&gt; 38:  cmp   r0, r2&lt;br /&gt; 3c:  str   r3, [ip]&lt;br /&gt; 40:  bne   30 &amp;lt;handle_swi+0x30&amp;gt;&lt;br /&gt; 44:  mov   r0, #0 ; 0x0&lt;br /&gt; 48:  b     10 &amp;lt;handle_swi+0x10&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Upon entry, &lt;code&gt;r0&lt;/code&gt; is among a few registers that is saved on the stack. Upon return, at addresses 0x10 and 0x14, register &lt;code&gt;r0&lt;/code&gt; and the other registers are restored. As such the return value, which is set at address 0x44, has been clobbered.&lt;br /&gt;&lt;br /&gt;After some more reading on GCC &lt;a href="http://gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Function-Attributes.html"&gt;function attributes&lt;/a&gt;, it appeared that attribute &lt;code&gt;naked&lt;/code&gt; could be used, but we need to insert inline assembly code for the prologue and epilogue ourselves. Somebody in the GNUARM mailing list thread also suggested something along this line. That is, we would do something like this instead:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;static int *out = (int *) 0x08000000;&lt;br /&gt;&lt;br /&gt;int __attribute__((naked))&lt;br /&gt; handle_swi(int reason, void *args) {&lt;br /&gt;&lt;br /&gt; asm("stmdb sp!,{r4-r11,ip,lr}");&lt;br /&gt; int r, i, n, *a;&lt;br /&gt; char *s;&lt;br /&gt; r = 0;&lt;br /&gt; if (reason != 5) r = -1;&lt;br /&gt; else {&lt;br /&gt;  a = (int*) args;&lt;br /&gt;  s = (char *) a[1];&lt;br /&gt;  n = a[2];&lt;br /&gt;  for (i=0; i&amp;lt;n; ++i) *out = s[i];&lt;br /&gt; }&lt;br /&gt; asm("ldmia sp!,{r4-r11,ip,lr};movs pc,lr");&lt;br /&gt; return r;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So much for trying to avoid assembly code in SWI handler. I choose not to save &lt;code&gt;r0&lt;/code&gt; to &lt;code&gt;r3&lt;/code&gt; because they are allowed to be clobbered in a function called. But the rest of the registers need to be saved and restored because we won't know how the C code would generally use them.&lt;br /&gt;&lt;br /&gt;At this point, I came to the conclusion that avoiding assembly code from SWI handler is rather difficult. Actually, we need to do more than just the epilogue and prologue code. So instead of sprinkling inline assembly code in the C function, I came up with a consolidated assembly code wrapper that does the necessary checking and other preparation before calling a straight C function to handle the SWI call.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;__swi_handler:&lt;br /&gt;  stmdb  sp!,{r4,lr}&lt;br /&gt;&lt;br /&gt;  /* see if SWI argument is 0x123456 */&lt;br /&gt;  ldr    r4,[lr,#-4]&lt;br /&gt;  bic    r4,r4,#0xff000000&lt;br /&gt;  sub    r4,r4,#0x00120000&lt;br /&gt;  sub    r4,r4,#0x00003400&lt;br /&gt;  subs   r4,r4,#0x00000056&lt;br /&gt;&lt;br /&gt;  /* save SPSR so that we have SWI reentrancy */&lt;br /&gt;  mrs    r4,spsr&lt;br /&gt;  stmdb  sp!,{r4}&lt;br /&gt;&lt;br /&gt;  /* only call handler if SWI argument is 0x123456 */&lt;br /&gt;  bleq   swi_handler&lt;br /&gt;&lt;br /&gt;  /* restore SPSR */  &lt;br /&gt;  ldmia  sp!,{r4}&lt;br /&gt;  msr    spsr,r4&lt;br /&gt;&lt;br /&gt;  ldmia  sp!,{r4,pc}^&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now we just need to make sure SWI vector address calls &lt;code&gt;__swi_handler&lt;/code&gt;. And remove the attribute modifier from &lt;code&gt;swi_handler&lt;/code&gt; function definition.&lt;br /&gt;&lt;br /&gt;Actually, there are more to SWI handling than just Angel SWI as can be gathered from the GNUARM thread mentioned earlier. For example, someone pointed out that divide-by-zero error will cause a SWI call. We may want to handle this properly too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27209140-115258116353751992?l=koda-karma.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://koda-karma.blogspot.com/feeds/115258116353751992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27209140&amp;postID=115258116353751992' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/115258116353751992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/115258116353751992'/><link rel='alternate' type='text/html' href='http://koda-karma.blogspot.com/2006/07/newlib-angel-swi-handing-in-c.html' title='Newlib Angel SWI handing in C'/><author><name>myusri</name><uri>http://www.blogger.com/profile/10829992323167955133</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27209140.post-115141699929639307</id><published>2006-06-27T21:15:00.000+08:00</published><updated>2006-06-27T22:07:14.986+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ARM'/><category scheme='http://www.blogger.com/atom/ns#' term='gcc'/><category scheme='http://www.blogger.com/atom/ns#' term='optimization'/><title type='text'>Mind your struct's!</title><content type='html'>This should be elementary to seasoned C programmers but one rule of thumb is, in a &lt;code&gt;struct&lt;/code&gt;, one should arrange the fields based on the size of their types in reverse order. This would typically lead to a more compact &lt;code&gt;struct&lt;/code&gt; which can be crucial to an embedded system with limited memory. To illustrate, &lt;code&gt;struct_a&lt;/code&gt; below is a &lt;code&gt;struct&lt;/code&gt; similar to what I've found in a library provided by a partner of my company. One the other hand, &lt;code&gt;struct_b&lt;/code&gt; is the same &lt;code&gt;struct&lt;/code&gt; but with its fields "properly ordered". In addition, the array &lt;code&gt;arr_a&lt;/code&gt; also appears in similar fashion in the partner's library.&lt;pre&gt;&lt;br /&gt;#include &lt;stdio.h&gt;&lt;br /&gt;&lt;br /&gt;struct struct_a {&lt;br /&gt;  short f1;&lt;br /&gt;  char  f2;&lt;br /&gt;  int   f3;&lt;br /&gt;  char  f4;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;struct struct_b {&lt;br /&gt;  int f3;&lt;br /&gt;  short f1;&lt;br /&gt;  char f2;&lt;br /&gt;  char f4;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;struct struct_a arr_a[32];&lt;br /&gt;struct struct_b arr_b[32];&lt;br /&gt;&lt;br /&gt;int main() {&lt;br /&gt;  printf("sizeof(struct_a):%d\n", sizeof(struct struct_a));&lt;br /&gt;  printf("sizeof(struct_b):%d\n", sizeof(struct struct_b));&lt;br /&gt;  printf("   sizeof(arr_a):%d\n", sizeof(arr_a));&lt;br /&gt;  printf("   sizeof(arr_b):%d\n", sizeof(arr_b));&lt;br /&gt;  return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Compiling the code above using the GNUARM toolchain and running it the ARM simulator in GDB, we get this output:&lt;pre&gt;&lt;br /&gt;sizeof(struct_a):12&lt;br /&gt;sizeof(struct_b):8&lt;br /&gt;   sizeof(arr_a):384&lt;br /&gt;   sizeof(arr_b):256&lt;br /&gt;&lt;/pre&gt;Simply by reordering the fields, we could save 4 bytes in the &lt;code&gt;struct&lt;/code&gt; and 128 bytes from the array above. Another example is given below. Again &lt;code&gt;struct_a&lt;/code&gt; is something found in the library and &lt;code&gt;struct_b&lt;/code&gt; is an optimized version of the &lt;code&gt;struct&lt;/code&gt;.&lt;pre&gt;&lt;br /&gt;#include &lt;stdio.h&gt;&lt;br /&gt;&lt;br /&gt;struct struct_a {&lt;br /&gt;   short f1;&lt;br /&gt;   int   f2;&lt;br /&gt;   char  f3;&lt;br /&gt;   char  f4;&lt;br /&gt;   short f5;&lt;br /&gt;   char  f6;&lt;br /&gt;   short f7;&lt;br /&gt;   short f8[3];&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;struct struct_b {&lt;br /&gt;   int   f2;&lt;br /&gt;   short f8[3];&lt;br /&gt;   short f1;&lt;br /&gt;   short f7;&lt;br /&gt;   short f5;&lt;br /&gt;   char  f3;&lt;br /&gt;   char  f4;&lt;br /&gt;   char  f6;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;struct struct_a arr_a[32];&lt;br /&gt;struct struct_b arr_b[32];&lt;br /&gt;&lt;br /&gt;int main() {&lt;br /&gt;  printf("sizeof(struct_a):%d\n", sizeof(struct struct_a));&lt;br /&gt;  printf("sizeof(struct_b):%d\n", sizeof(struct struct_b));&lt;br /&gt;  printf("   sizeof(arr_a):%d\n", sizeof(arr_a));&lt;br /&gt;  printf("   sizeof(arr_b):%d\n", sizeof(arr_b));&lt;br /&gt;  return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The output of the program compiled through GNUARM toolchain is given below.&lt;pre&gt;&lt;br /&gt;sizeof(struct_a):24&lt;br /&gt;sizeof(struct_b):20&lt;br /&gt;   sizeof(arr_a):768&lt;br /&gt;   sizeof(arr_b):640&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Again, we could save 4 bytes from the &lt;code&gt;struct&lt;/code&gt; and 128 bytes from the array. Note that &lt;code&gt;struct_b&lt;/code&gt; above has a &lt;code&gt;short&lt;/code&gt; array with 3 elements as a field. Why it was not made the first field of &lt;code&gt;struct_b&lt;/code&gt;? After all it is bigger than an &lt;code&gt;int&lt;/code&gt;. It has something to do with &lt;code&gt;int&lt;/code&gt; alignment on ARM. Try it out and see.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27209140-115141699929639307?l=koda-karma.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://koda-karma.blogspot.com/feeds/115141699929639307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27209140&amp;postID=115141699929639307' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/115141699929639307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/115141699929639307'/><link rel='alternate' type='text/html' href='http://koda-karma.blogspot.com/2006/06/mind-your-structs.html' title='Mind your struct&apos;s!'/><author><name>myusri</name><uri>http://www.blogger.com/profile/10829992323167955133</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27209140.post-115106412957186748</id><published>2006-06-23T19:42:00.000+08:00</published><updated>2006-06-23T20:02:09.583+08:00</updated><title type='text'>Using interrupts for super responsive tasks?</title><content type='html'>I read an interesting article at Embedded.com titled "A&lt;a href="http://www.embedded.com/showArticle.jhtml?articleID=189501160"&gt; data-centric OS for MCUs using a real-time publisher-subscriber-mechanism: Part1&lt;/a&gt;" and it is very interesting. Typically, in embedded system, you would use a preemptive OS which run tasks based on task priorities on a predefined timeslice. This article, however, proposes a publish-and-subscribe task model using interrupts and interrupt priorities. So no OS in the traditional sense. Basically, each task is an interrupt handler.&lt;br /&gt;&lt;br /&gt;A task can be a consumer or a producer. The producer task would trigger an interrupt through software when an interesting event occurs. The consumer task would subscribe to that event by registering an interrupt handler as the event call back function. The interrupt priorities would be used to decide which event handler would be called in the event that many event handlers are eligible to run. Nested interrupt is also enabled.&lt;br /&gt;&lt;br /&gt;The interrupt controller we are using for our SoC supports up to 64 interrupt sources that can also be programmatically triggered. It also has 16 interrupt priorities with programmable interrupt handler each to play with. It would be interesting to see how the suggested technique in the article could be mapped to it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27209140-115106412957186748?l=koda-karma.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://koda-karma.blogspot.com/feeds/115106412957186748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27209140&amp;postID=115106412957186748' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/115106412957186748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/115106412957186748'/><link rel='alternate' type='text/html' href='http://koda-karma.blogspot.com/2006/06/using-interrupts-for-super-responsive.html' title='Using interrupts for super responsive tasks?'/><author><name>myusri</name><uri>http://www.blogger.com/profile/10829992323167955133</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27209140.post-114778396712396610</id><published>2006-05-16T20:13:00.000+08:00</published><updated>2006-05-16T22:41:07.763+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='debugging'/><title type='text'>But it worked before...</title><content type='html'>I helped a colleague early last week. His PPP server running on VxWorks on our Carmen II board used to run okay a few weeks back. But when he started to work on it again a couple of weeks ago, it gave no response to PPP connection attempts from a Windows PC. My first instinct was to check the RS232 connection to the board because the connection requires manual wiring to the board (the only DB-9 connector on the board has been allocated for the console). However, according to my colleague the connection worked because his AT command processor running on the board received bytes from the PC. Moreover, the test program we had to test the two serial ports seemed to transfer bytes just fine. So both of us went on to debug the PPP configuration. We went as far as using the base BSP we have by including PPP in it. Still we could not get PPP to work. The following morning, I finally decided to look at the connection. Well, lo and behold, the connection was "half correct" which explains why the AT command processor could still receive bytes. I think you can guess what had happened and I will leave it at that.&lt;br /&gt;&lt;br /&gt;Yesterday, I helped another colleague to debug the board with the design she had downloaded into the FPGA. A "similar" design had worked before. By "working", we mean we could get our in-circuit-emulator (ICE) to bring ARM into the background debug mode (BDM). She has been debugging her design for a number of days already. Initially, I thought the ICE used the DBGRQ and DBGACK signals to enter BDM. Apparently not. So there is no other way for the ICE to do that except through the JTAG serial protocol. With the help of a logic analyzer we watched the 5 JTAG signals both with the good and the bad designs on the board's FPGA. Immediately we saw that there was some problem with the nTRST signal. The signal was oscillating on the bad design whereas, in the good design, it started low and then high, followed by some activity on the TMS, TDI and TDO signals. Looking at the board schematic, we could see that the nTRST signal from the JTAG connector goes first to the FPGA and then from there to the ARM. So there must have been bad connection between these two points on the FPGA. Sure enough. When she rechecked her UCF file for the design, the nTRST input into the FPGA was not connected to the reset controller module which drives some other logic before going out to the ARM.&lt;br /&gt;&lt;br /&gt;So, the lesson is, I guess, before going on debugging your design or code check all of the manual connections you have made. Especially when it has worked before.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27209140-114778396712396610?l=koda-karma.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://koda-karma.blogspot.com/feeds/114778396712396610/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27209140&amp;postID=114778396712396610' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/114778396712396610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/114778396712396610'/><link rel='alternate' type='text/html' href='http://koda-karma.blogspot.com/2006/05/but-it-worked-before.html' title='But it worked before...'/><author><name>myusri</name><uri>http://www.blogger.com/profile/10829992323167955133</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27209140.post-114705772506653702</id><published>2006-05-08T10:06:00.000+08:00</published><updated>2006-05-16T20:07:16.620+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='newlib'/><category scheme='http://www.blogger.com/atom/ns#' term='Angel SWI'/><title type='text'>newlib printf through UART on GNU ARM toolchain</title><content type='html'>To make function like &lt;code&gt;printf&lt;/code&gt; and &lt;code&gt;puts&lt;/code&gt; to work on the GNUARM toolchain,  the Angel SWI handler for the &lt;code&gt;AngelSWI_Reason_Write&lt;/code&gt; command needs to be implemented. This command is indicated through value 5 in register &lt;code&gt;r0&lt;/code&gt; when the Angel SWI call is made. Register &lt;code&gt;r1&lt;/code&gt; will point to an array of 3 32-bit values. The first is a file pointer which I will ignore because I do not do any other file operation except writing to &lt;code&gt;stdout&lt;/code&gt;. The second is a pointer to the array of &lt;code&gt;char&lt;/code&gt;'s to print. The third contains the length of the string. Below is the code snippet for the SWI handler:&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;pre&gt;__swi_handler:&lt;br /&gt;  cmp    r0,#5&lt;br /&gt;  bne    .Ldone&lt;br /&gt;&lt;br /&gt;  /* skip file pointer and store char pointer in r0&lt;br /&gt;     and length into r1 */&lt;br /&gt;&lt;br /&gt;  ldr    r0,[r1,#4]!&lt;br /&gt;  ldr    r1,[r1,#4]&lt;br /&gt;&lt;br /&gt;  add    r1,r1,r0  /* now r1 points to end of chars to print */&lt;br /&gt;&lt;br /&gt;  mov    r2,#UARTA_BASE&lt;br /&gt;&lt;br /&gt;.Lnext:&lt;br /&gt;  ldr    r3,[r2,#LSR]&lt;br /&gt;  ands   r3,r3,#LSR_THRE&lt;br /&gt;  beq    .Lnext&lt;br /&gt;  &lt;br /&gt;  ldrb   r3,[r0],#1&lt;br /&gt;  str    r3,[r2,#THR]&lt;br /&gt;&lt;br /&gt;  /* append CR if we see a NL */&lt;br /&gt;&lt;br /&gt;  cmp    r3,#0x0A    /* NL? */&lt;br /&gt;  moveq  r3,#0x0D    /* CR  */&lt;br /&gt;  streq  r3,[r2,#THR]&lt;br /&gt;&lt;br /&gt;  cmp    r0,r1&lt;br /&gt;  blt    .Lnext&lt;br /&gt;  mov    r0,#0&lt;br /&gt;.Ldone:&lt;br /&gt;  movs  pc,lr&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;I am being a little bit sloppy above by not checking that the SWI instruction that triggers the call does in fact have a &lt;code&gt;0x123456&lt;/code&gt; as its argument which is required for Angel SWI. Of course, the ARM exception vectors needs to be configured accordingly:&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;pre&gt;__vec_start__:&lt;br /&gt;  LDR   PC, Reset_Addr   &lt;br /&gt;  LDR   PC, Undef_Addr&lt;br /&gt;  LDR   PC, SWI_Addr&lt;br /&gt;  LDR   PC, PAbt_Addr&lt;br /&gt;  LDR   PC, DAbt_Addr&lt;br /&gt;  NOP&lt;br /&gt;  LDR   PC, IRQ_Addr&lt;br /&gt;  LDR   PC, FIQ_Addr&lt;br /&gt;&lt;br /&gt;Reset_Addr:   .word   start&lt;br /&gt;Undef_Addr:   .word   Undef_Handler&lt;br /&gt;SWI_Addr:     .word   __swi_handler&lt;br /&gt;PAbt_Addr:    .word   PAbt_Handler&lt;br /&gt;DAbt_Addr:    .word   DAbt_Handler&lt;br /&gt;             .word   0&lt;br /&gt;IRQ_Addr:     .word   IRQ_Handler&lt;br /&gt;FIQ_Addr:     .word   FIQ_Handler&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;And the UART needs to be configured properly before use. I have the code below in my &lt;code&gt;crt0.S&lt;/code&gt; to initialize the UART. You need to program the DLL and DLH (Divisor Latch registers) according to your UART clock and the desired baud rate:&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;pre&gt;  mov    r0,#UARTA_BASE&lt;br /&gt;  mov    r1,#0x07&lt;br /&gt;  str    r1,[r0,#FCR]  /* reset and enable FIFOs */&lt;br /&gt;  mov    r1,#0x00&lt;br /&gt;  str    r1,[r0,#IER]  /* no interrupt */&lt;br /&gt;  mov    r1,#0x80&lt;br /&gt;  str    r1,[r0,#LCR]  /* to program divisor */&lt;br /&gt;  mov    r1,#0x41      /* change this if clock change! */&lt;br /&gt;  str    r1,[r0,#DLL]&lt;br /&gt;  mov    r1,#0x00&lt;br /&gt;  str    r1,[r0,#DLH]&lt;br /&gt;  mov    r1,#0x03&lt;br /&gt;  str    r1,[r0,#LCR]  /* 8 bit, 1 stop bit */&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27209140-114705772506653702?l=koda-karma.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://koda-karma.blogspot.com/feeds/114705772506653702/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27209140&amp;postID=114705772506653702' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/114705772506653702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/114705772506653702'/><link rel='alternate' type='text/html' href='http://koda-karma.blogspot.com/2006/05/newlib-printf-through-uart-on-gnu-arm.html' title='newlib printf through UART on GNU ARM toolchain'/><author><name>myusri</name><uri>http://www.blogger.com/profile/10829992323167955133</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27209140.post-114658171014409374</id><published>2006-05-02T22:33:00.000+08:00</published><updated>2006-05-02T23:03:53.070+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Java SE for Embedded Use</title><content type='html'>I supposed Sun has now realized that there is a place for Java SE (Java Platform, Standard Edition), in addition to Java ME (Java Platform, Mobile Edition), in the embedded market. They have just released an early access to Java SE for PowerPC running Linux. See &lt;a href="http://java.sun.com/j2se/embedded/"&gt;http://java.sun.com/j2se/embedded/&lt;/a&gt;. But to download you need to answer a questionnaire first. I guess it is good to complete the questionnaire to give Sun what embedded platforms we would like to see Java SE runs on. (But the questionnaire does not list my country for me to pick!)&lt;br /&gt;&lt;br /&gt;We are currently using ARM7 at work. Since the full-fledge Linux does not run on ARM7 due to a missing MMU, I guess we won't be seeing Java SE for ARM7 any time soon. Unless someone does the porting to uClinux.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27209140-114658171014409374?l=koda-karma.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://koda-karma.blogspot.com/feeds/114658171014409374/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27209140&amp;postID=114658171014409374' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/114658171014409374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/114658171014409374'/><link rel='alternate' type='text/html' href='http://koda-karma.blogspot.com/2006/05/java-se-for-embedded-use.html' title='Java SE for Embedded Use'/><author><name>myusri</name><uri>http://www.blogger.com/profile/10829992323167955133</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27209140.post-114623453907726528</id><published>2006-04-28T22:02:00.000+08:00</published><updated>2006-04-28T22:38:44.683+08:00</updated><title type='text'>It's hard to pick a name!</title><content type='html'>It is hard to pick a good name for my blog!&lt;br /&gt;&lt;br /&gt;I have been doing embedded software development on ARM processor at my new job for about a year now. I thought kARMa would be a good name play with ARM moniker. Only that name is taken already. So I have to settle with "Koda.Karma."&lt;br /&gt;&lt;br /&gt;I would like to believe "koda" is  a corruption of the English word "code" into the Malay language but I could not confirm this from the scarce Malay dictionaries on the Internet.&lt;br /&gt;&lt;br /&gt;So there you have it. My first blog entry here and an attempt at a good sounding blog name. Welcome to Koda.Karma!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27209140-114623453907726528?l=koda-karma.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://koda-karma.blogspot.com/feeds/114623453907726528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27209140&amp;postID=114623453907726528' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/114623453907726528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27209140/posts/default/114623453907726528'/><link rel='alternate' type='text/html' href='http://koda-karma.blogspot.com/2006/04/its-hard-to-pick-name.html' title='It&apos;s hard to pick a name!'/><author><name>myusri</name><uri>http://www.blogger.com/profile/10829992323167955133</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
