

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>pavius.net: no refunds</title>
	<atom:link href="http://www.pavius.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.pavius.net</link>
	<description>Embedded software development and working with those annoying computers in general</description>
	<lastBuildDate>Sat, 31 Mar 2012 08:39:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Access windows share in Fedora 15</title>
		<link>http://www.pavius.net/2011/09/access-windows-share-in-fedora-15/</link>
		<comments>http://www.pavius.net/2011/09/access-windows-share-in-fedora-15/#comments</comments>
		<pubDate>Sun, 25 Sep 2011 07:20:03 +0000</pubDate>
		<dc:creator>Eran Duchan</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.pavius.net/?p=52</guid>
		<description><![CDATA[Needing an RPM based distro, I fired up Fedora on a VM. I was never a fan of Fedora and 15 felt right at home &#8211; half baked cutting edge features shoved into your face, leaving you struggling to find the equivalent of even the basic interaction. Still, I needed to connect to windows shares [...]]]></description>
			<content:encoded><![CDATA[<div class="blog-post-img"><a href="2011/06/access-windows-share-in-fedora-15"> <img class="attachment-post_box_img wp-post-image" src="/wp-content/uploads/fedora-share/header.jpg" alt="" width="640" /></a></div>
<p>Needing an RPM based distro, I fired up Fedora on a VM. I was never a fan of Fedora and 15 felt right at home &#8211; half baked cutting edge features shoved into your face, leaving you struggling to find the equivalent of even the basic interaction. Still, I needed to connect to windows shares on a FreeNAS and google was of little to no help. Here&#8217;s what worked for me.<br />
<span id="more-52"></span></p>
<p>First install samba and samba-client</p>
<pre>sudo yum install -y samba
sudo yum install -y samba-client</pre>
<p>Then install the &#8220;places&#8221; gnome menu. It will appear as an icon on the right rather than a drop-down menu on the left.</p>
<pre>sudo yum install -y gnome-shell-extensions-places-menu</pre>
<p>Now you need to play around with your security policies. I run with SELinux disabled so I&#8217;m not sure what it would take to get a specific samba-friendly policy &#8211; you&#8217;ll have to google that. In addition, you&#8217;ll need to turn off your firewall or enable samba through it (I run without it). Now logout or reboot.</p>
<p>You can now use the familiar Places -> connect to dialogue to connect to the share.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pavius.net/2011/09/access-windows-share-in-fedora-15/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>lpicp, the embedded Linux PIC programmer</title>
		<link>http://www.pavius.net/2011/06/lpicp-the-embedded-linux-pic-programmer/</link>
		<comments>http://www.pavius.net/2011/06/lpicp-the-embedded-linux-pic-programmer/#comments</comments>
		<pubDate>Wed, 08 Jun 2011 08:25:53 +0000</pubDate>
		<dc:creator>Eran Duchan</dc:creator>
				<category><![CDATA[Embedded Linux]]></category>
		<category><![CDATA[Microcontrollers]]></category>
		<category><![CDATA[Software tools]]></category>
		<category><![CDATA[embedded linux]]></category>
		<category><![CDATA[lpicp]]></category>
		<category><![CDATA[pic]]></category>
		<category><![CDATA[pic programmer]]></category>

		<guid isPermaLink="false">http://www.pavius.net/?p=49</guid>
		<description><![CDATA[This is probably not what you think it is. It is not an application that controls ICD2, PicKit2 or any form of custom LPT PIC programmer for a PC (you can use MPLAB X for that). What lpicp does is provide a user space application and kernel driver to perform the functionality of a PIC [...]]]></description>
			<content:encoded><![CDATA[<div class="blog-post-img"><a href="2011/06/lpicp-the-embedded-linux-pic-programmer"> <img class="attachment-post_box_img wp-post-image" src="/wp-content/uploads/lpicp/header.jpg" alt="" width="640" /></a></div>
<p>This is probably not what you think it is. It is not an application that controls ICD2, PicKit2 or any form of custom LPT PIC programmer for a PC (you can use <a href="http://www.microchip.com/en_US/family/mplabx/index.html">MPLAB X</a> for that). What lpicp does is provide a user space application and kernel driver to perform the functionality of a PIC programmer on embedded systems running Linux. <span id="more-49"></span>After deploying these modules onto such a system (and assuming the hardware is layed out properly), you can run something like:<br />
<br/></p>
<pre>
lpicp -x write -d /dev/icsp0 -f my-pic-program.hex
</pre>
<p>and have your embedded system program a Microchip PIC microcontroller via an ICSP bus.</p>
<p><h2 class="post-heading">Implementing the ICSP protocol and bus</h2><hr class="post-heading" /><br />
Microchip has devised a simple 4 wire bus to allow for programming the PIC devices. In reality, the majority of the physical protocol is over 2 wires &#8211; pgc (clock) and pgd (data). The bus master (the programmer) clocks out 4 command bits followed by 16 data bits. The commands are specified in the flash programming spec for each device but they can be divided into three main groups:</p>
<ul>
<li>Read</li>
<li>Write</li>
<li>Execute instruction</li>
</ul>
<p>To implement a high level operation like reading a device requires a mixture of commands, spanning across all the three groups; simplisticly you&#8217;d have to execute instructions to prepare the PIC, write the address pointer and read data. You really must read the flash programming spec to understand the specifics, but the jist is the same for all high level operations (erase/read/write).<br />
<div class="img-frame"><a rel="lightbox" href="/wp-content/uploads/lpicp/board.jpg" title="PPC based board implementing ICSP" ><span><img class="img-frame " src="/wp-content/themes/dandelion_v2.6.1/functions/timthumb.php?src=/wp-content/uploads/lpicp/board.jpg&amp;w=650h=&amp;zc=1" alt="" /></span></a></div>Since no hardware controller exists for operating the bus transactions, we are required to bit bang it. The hardware protocol itself is very simple (although very inconsistent across operations and devices). I had the option of implementing the bus protocol entirely in userspace and using the platform independent GPIO infrastructure but this does not achieve the desired bus timing (despite the fact that the PICs are very lax in their timing, especially in maximum values, I still wanted the bus to look as clean as possible).</p>
<p>To do this, I offloaded all bus transactions to a platform driver (mc_icsp) using callbacks to the platform (which toggles the GPIOs). All timing is configured when registering the platform driver and user space interacts with it via /dev using 4 ioctls:</p>
<ul>
<li>transmit: send 4 bit command and write 16 bits of data</li>
<li>receive: send 4 bit command and read 16 bits of data</li>
<li>send command only: send only the 4 bit command with a configurable waveform</li>
<li>send data only: send only 16 bits of data</li>
</ul>
<p><h2 class="post-heading">Userland</h2><hr class="post-heading" /><br />
<div class="img-frame"><a rel="lightbox" href="/wp-content/uploads/lpicp/lpicp-block-diagram.png" title="lpicp block diagram" ><span><img class="img-frame alignright" src="/wp-content/themes/dandelion_v2.6.1/functions/timthumb.php?src=/wp-content/uploads/lpicp/lpicp-block-diagram.png&amp;w=300h=&amp;zc=1" alt="" /></span></a></div>The user space application, lpicp, takes care of receiving the command from the user, parsing Intel HEX records and performing the higher levels ICSP protocol. This is very device specific so there is framework in place to allow for adding devices without ugly ifs() and #ifdefs. </p>
<p>The application is built using cmake, which outputs liblpicp.a and an lpicp executable. The executable adds a command line layer, but you can just as well link to liblpicp.a to integrate PIC programming into your application. The lpicp executable can be run with the following arguments:</p>
<p>  -x, &#8211;exec: r, read | w, write | e, erase | devid<br />
  -d, &#8211;dev: ICSP device name (e.g. /dev/icsp0)<br />
  -f, &#8211;file: Path to Intel HEX file<br />
  -o, &#8211;offset: Read from offset, Write to offset<br />
  -s, &#8211;size: Size for operation, in bytes<br />
  -v, &#8211;verbose: Verbose operation</p>
<p>The application uses <a href="http://dev.frozeneskimo.com/software_projects/libgis">libGIS</a>&#8216;s ihex.c module to parse the Intel HEX record file outputted by PIC compilers. The files contain data records to be written to program, configuration and eeprom memory. The application knows where to burn each record according to its address.</p>
<p><h2 class="post-heading">Getting the source</h2><hr class="post-heading" /><br />
This project is really in its infancy and will probably only ever serve as reference. I was contracted to implement this for PIC18F452 and PIC18F4520 and this is what works. Browse the README @ github to understand the limitations of the current version and build instructions.</p>
<p>You can get the lpicp code @ the <a href="https://github.com/pavius/lpicp">lpicp github repo</a> and the driver can be found <a href="/wp-content/uploads/lpicp/mc_icsp.7z">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pavius.net/2011/06/lpicp-the-embedded-linux-pic-programmer/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Implementation notes for Embedded Linux</title>
		<link>http://www.pavius.net/2011/05/implementation-notes-for-embedded-linux/</link>
		<comments>http://www.pavius.net/2011/05/implementation-notes-for-embedded-linux/#comments</comments>
		<pubDate>Thu, 12 May 2011 21:14:22 +0000</pubDate>
		<dc:creator>Eran Duchan</dc:creator>
				<category><![CDATA[Embedded Linux]]></category>
		<category><![CDATA[embedded linux]]></category>
		<category><![CDATA[self]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.pavius.net/?p=45</guid>
		<description><![CDATA[This post hosts a few blurbs about issues I ran into when developing for Embedded Linux and did not find decent documentation on google. It will update as I plow through more stuff. By default, if you try to connect to the server, you&#8217;ll get an error claiming &#8220;all network ports in use&#8221;. This is [...]]]></description>
			<content:encoded><![CDATA[<div class="blog-post-img"><a href="2011/05/implementation-notes-for-embedded-linux"> <img class="attachment-post_box_img wp-post-image" src="/wp-content/uploads/imp-notes/header.jpg" alt="" width="640" /></a></div>
<p>This post hosts a few blurbs about issues I ran into when developing for Embedded Linux and did not find decent documentation on google. It will update as I plow through more stuff.<span id="more-45"></span></p>
<p><h2 class="post-heading">Getting the telnet server (telnetd) to accept connections when using DENX SELF</h2><hr class="post-heading" /><br />
By default, if you try to connect to the server, you&#8217;ll get an error claiming &#8220;all network ports in use&#8221;. This is not so much of a SELF configuration thing, rather how the kernel is set up by default. Assuming you ran MAKEDEV (see my <a href="http://www.pavius.net/2011/01/building-uboot-linux-ppc/">installation post</a>) when installing the ELDK, you&#8217;ll have a few /dev/ttyp devices. As I understand, telnetd attaches to these pseudo ttys to send/receive data from a user (one each). However, the kernel is not set up by default to install the driver for PTY devices. </p>
<p>The solution is to run menuconfig (or xconfig) and include the Legacy PTY device support in the kernel (under Device Drivers -> Character Devices). After you&#8217;ve deployed your kernel, telnet should be able to connect. Make sure to create a user with a shell for telnet, otherwise you won&#8217;t be able to log in.</p>
<p><h2 class="post-heading">Setting up the FTP server for upload support when using DENX SELF</h2><hr class="post-heading" /><br />
The SELF image has wu-ftpd set up, but it does not allow uploading files by default. Doing this is rather simple &#8211; simply modify /etc/ftpaccess as follows:</p>
<ul>
<li>Change the &#8220;no&#8221; just right of chmod, delete, overwrite to &#8220;yes&#8221;</li>
<li>Add &#8220;upload / * yes&#8221; with no quotation marks just below this list </li>
</ul>
<p><h2 class="post-heading">Some images segfault before main</h2><hr class="post-heading" /><br />
This one had me scratching my head for a few hours. I wanted to deploy dropbear on the target so I downloaded the latest source and compiled it. I then went ahead to deploy dropbear and dropbearkey only to see that dropbear shows a segmentation fault before main. At first I thought it was some shared library issue, but setting the LD debug flag did not print out anything &#8211; it was crashing before pulling in any objects.</p>
<p>I thought perhaps the kernel was not configured properly for ELF files but it was. I then rebuilt binutils (so that I will have the latest and greatest) and ran readelf on my Ubuntu station on both dropbear and dropbearkey &#8211; it showed everything was great. However, I then cross-compiled readelf and tried running it on the target&#8217;s dropbear and dropbearkey &#8211; it showed the dropbear ELF was corrupt (bad section header offsets).</p>
<p>After more investigation i saw an offset of 1 byte when reading the section headers &#8211; but only on the target. Looking manually at the hex dump for the dropbear image on my PC showed it was perfect. I then looked at the sizes of the images &#8211; dropbear on the target was 3 bytes smaller than dropbear on my PC, even though they&#8217;re the same file&#8230; </p>
<p>To make a long story short &#8211; it turns out that FileZilla (my FTP client) did some CR/LF manipulation when sending the file to the target. Setting the transfer mode from &#8220;Auto&#8221; to &#8220;Binary&#8221; did the trick. D&#8217;oh!</p>
<p><h2 class="post-heading">Using Eclipse to debug the kernel with Abatron BDI3000</h2><hr class="post-heading" /><br />
The Abatron BDI3000 supports a GDB frontend (bdiGDB) so we can pretty easily set up Eclipse to debug the kernel. I used an external plugin for this &#8211; the Zylin embedded CDT (download/installation instructions <a href="http://opensource.zylin.com/embeddedcdt.html">here</a>). Once that&#8217;s installed, we create a Debug configuration (Run -> Debug Configurations) under Zylin Embedded Debug (Native). In the Main tab we set the C/C++ application to the applicable vmlinux (there is no need to set a project) and in the Debugger tab we leave everything default and browse to set GDB debugger to the appropriate GDB (for example, ppc_8xx-gdb). Finally, in the Commands tab we set Initialize commands to &#8220;target remote {bdi-ip}:2001&#8243; and Run commands to &#8220;c&#8221;.</p>
<p>To actually perform debugging, I attach the GDB only after Linux has initialized the MMU (I chose to break at __start_here). To do this, I telnet to the BDI and perform: </p>
<pre>
reset
bi {__start_here offset, taken from the System.map file, e.g. bi 0xc00021e0}
go
</pre>
<p>The target should stop at __start_here. At this point I can set breakpoints to debug the kernel boot process and start debugging in Eclipse. To debug again, terminate the GDB process by clicking the red button or Ctrl+F2 and re-enter the BDI commands above. There is no need to do the clear/set  breakpoint dance with Eclipse &#8211; it will remember your breakpoint settings and reapply them every time you connect. The BDI does not do this, however, so you need to always re-perform bi.</p>
<p><h2 class="post-heading">Debugging U-Boot (after relocation) in Eclipse</h2><hr class="post-heading" /><br />
This is quite similar to debugging the Linux kernel in eclipse, so follow the above paragraph with the following differences.</p>
<ul>
<li>You need to obtain the address to which U-Boot relocates to in RAM. This can either be done <a href="http://www.denx.de/wiki/DULG/DebuggingUBoot">the DENX way</a> or by adding a printf to board_init_f, printing out the last argument, addr, to relocate_code</li>
<li>You&#8217;ll also need the address of board_init_r, which is called immediately after relocation to RAM. Just find it in u-boot.map and add its value to the relocation address you obtained in the first step. This will give you the absolute RAM address at which board_init_r resides after relocation</li>
<li>In the Main tab, instead of vmlinux you&#8217;ll need to point to the u-boot file in your U-Boot root directory</li>
<li>In the Commands tab, set &#8216;Initialize&#8217; to:
<ul>
<li>target remote {bdi-ip}:2001</li>
<li>symbol-file</li>
<li>add-symbol-file {u-boot-dir}/u-boot {u-boot-ram-relocation-address}</li>
</ul>
</li>
<li>In the BDI telnet session, follow the same thing as Linux debugging only break on board_init_r&#8217;s absolute RAM address</li>
</ul>
<p>The rest should behave just like Linux debugging &#8211; reset in BDI, set the breakpoint, go; target will stop, attach via Eclipse.</p>
<p><h2 class="post-heading">Applying a patch from GMail</h2><hr class="post-heading" /><br />
Many mailing lists have a host of patches, embedded inline posted messages. When subscribing to these lists with a GMail account, you may find yourself wanting to apply one such patch. The problem is that GMail&#8217;s web interfaces will manipulate the hell out of the received messages (whitespaces and line wraps mostly) &#8211; this will at best break checkpatch and at worst break compilation. </p>
<p>To create a working patch, I simply click on the little blue drop down icon on the upper-right corner of the message holding the patch and select &#8220;Show original&#8221;. You can safely copy/paste this into a text file and apply.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pavius.net/2011/05/implementation-notes-for-embedded-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementing a preemptive kernel within a single Windows thread</title>
		<link>http://www.pavius.net/2011/04/implementing-a-preemptive-kernel-within-a-single-windows-thread/</link>
		<comments>http://www.pavius.net/2011/04/implementing-a-preemptive-kernel-within-a-single-windows-thread/#comments</comments>
		<pubDate>Tue, 05 Apr 2011 19:08:15 +0000</pubDate>
		<dc:creator>Eran Duchan</dc:creator>
				<category><![CDATA[Embedded software]]></category>
		<category><![CDATA[Software tools]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[preemptive]]></category>
		<category><![CDATA[simulation]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.pavius.net/?p=42</guid>
		<description><![CDATA[About three years ago I developed a real-time operating system aimed at the new generation of 32 bit microcontrollers. Seeing how I am a devotee of developing/testing embedded software on a PC and only then porting/testing to the target, one of my goals was to get a working simulation environment under Windows. I had thought [...]]]></description>
			<content:encoded><![CDATA[<div class="blog-post-img"><a href="2011/04/implementing-a-preemptive-kernel-within-a-single-windows-thread"> <img class="attachment-post_box_img wp-post-image" src="/wp-content/uploads/preemptive-kernel/header.jpg" alt="" width="640" /></a></div>
<p>About three years ago I developed a real-time operating system aimed at the new generation of 32 bit microcontrollers. Seeing how I am a devotee of developing/testing embedded software on a PC and only then porting/testing to the target, one of my goals  was to get a working simulation environment under Windows. I had thought at the time that I would have a lot of reference, seeing how most real-time operating systems (<a href="http://www.freertos.org/index.html?http://www.freertos.org/FreeRTOS-Windows-Simulator-Emulator-for-Visual-Studio-and-Eclipse-MingW.html">FreeRTOS</a>, for example) have Windows ports. To my surprise no port implemented true preemption, instead opting for simply wrapping the Windows API with the equivalent RTOS API (for example, creating an RTOS thread would call Windows&#8217; CreateThread).<br />
<span id="more-42"></span><br />
Functionally this allows users to develop under Windows, calling the RTOS API as they would on the target and testing their application under Windows. However, there are two drawbacks to this:</p>
<ol>
<li>The result of such a simulation, while usually sufficient, is quite synthetic. A lot of behavior is due to change when porting back to the target because Windows cannot be (easily) made to behave like an RTOS &#8211; especially in the aspect of predictable scheduling</li>
<li>As an RTOS developer you can&#8217;t write and test kernel code under Windows and as an application developer you cannot familiarize yourself with the underlying kernel state at a given time, seeing how no such state exists</li>
</ol>
<p>It is therefore beneficial to have as much of the RTOS kernel as possible running under Windows and for the most part this is quite straightforward. <em>Most</em> context switches occur when the application calls an OS API &#8211; like sleep() or giving a semaphore. Let&#8217;s assume we have a single Windows thread and we implement the following piece of code:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// the first thread entry</span>
first_thread<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> counter <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// forever</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>TRUE<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// increment counter</span>
        counter<span style="color: #339933;">++;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// sleep for a period of 0 (yield the scheduler)</span>
        rtos_sleep<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// the second thread entry</span>
second_thread<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> counter <span style="color: #339933;">=</span> <span style="color: #208080;">0xFFFFFFFF</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// forever</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>TRUE<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// decrement counter</span>
        counter<span style="color: #339933;">--;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// same as first_thread</span>
        rtos_sleep<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>In this simple scenario, we create two RTOS threads and expect them to work concurrently. Seeing how we only have one Windows thread, we need to be able to switch between the two contexts (each thread has a stack and different register states). In this case, actual context switch will occur on the call to rtos_sleep(). If we were to follow the trace of execution (remember &#8211; we have only one Windows thread) we will see that it starts by entering first_thread, having the stack pointer pointing to the first thread&#8217;s stack. It will then increment the counter on first_thread&#8217;s stack and enter rtos_sleep. This kernel function will revoke the first_thread&#8217;s right to continue and then load the second_thread&#8217;s context (its stack and registers). The Windows thread will then continue to execute and, seeing how it loaded second_thread&#8217;s instruction pointer register, start running second_thread.</p>
<div class="img-frame"><a rel="lightbox" href="/wp-content/uploads/preemptive-kernel/cooperative.png" title="Example of simulating a cooperative kernel in a single Windows thread" ><span><img class="img-frame " src="/wp-content/themes/dandelion_v2.6.1/functions/timthumb.php?src=/wp-content/uploads/preemptive-kernel/cooperative.png&amp;w=650h=&amp;zc=1" alt="" /></span></a></div>
<p>Such behavior can allow for simulating a LOT of functionality &#8211; thread priority, thread state, waitable objects like semaphores, and the like &#8211; but all of the context switches can only be made when the user calls an RTOS API. Effectively, we have simulated a <em>cooperative kernel</em>, in which the user must call the kernel every so often to enable other threads to run. There are so many examples of implementing a cooperative context switching mechanism in Windows out there that I am not going to go into the details of how we actually do the magic behind this example (creating the thread, swapping contexts and the like). I&#8217;m sure Google can provide many excellent sources. </p>
<p><h2 class="post-heading">From cooperative to preemptive</h2><hr class="post-heading" /><br />
We are interested in allowing for these two threads above to share CPU without calling an RTOS API. We want to be able to have the first_thread loop in place and still allow for second_thread to run. This will allow us to implement timers, interrupts and time-slice scheduling (that is, sharing CPU fairly among same priority ready-to-run threads). To be honest I was quite stumped with this for a few days. I needed to find a way to somehow alter the flow of execution of the Windows thread running the kernel, whichever block of code it may be running. When I figured out how to do this I was pretty awe struck at how simple it is.</p>
<p>We start by spawning a second Windows thread &#8211; this thread will serve as the interrupt thread. Overall, we will only need two Windows threads: the interrupt thread (running in high Windows priority) and the kernel thread (running in normal Windows priority), which will run the RTOS threads, however many they may be. Whenever we&#8217;d like interrupted rescheduling to be performed we post a message into the interrupt thread&#8217;s Windows message queue. This will be either periodically (using an auto-renewing timer) or deferred (using a one-shot timer). </p>
<p>The magic occurs once the interrupt thread receives the request to interrupt. At this point in time, the interrupt thread will simply hi-jack the kernel thread &#8211; changing its current point of execution to a block of code that performs saving the current context and loading the next one. This is done by using GetThreadContext and SetThreadContext.</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// hijack the windows thread running our kernel - once</span>
<span style="color: #666666; font-style: italic;">// it becomes ready it will jump to wcs_isr_reschedule</span>
<span style="color: #993333;">void</span> wcs_intsim_do_interrupt<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #666666; font-style: italic;">// initialize context flags </span>
	CONTEXT ctx<span style="color: #339933;">;</span>
		memset<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>ctx<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>ctx<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		ctx.<span style="color: #202020;">ContextFlags</span> <span style="color: #339933;">=</span> CONTEXT_FULL<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// suspend the kernel thread</span>
	SuspendThread<span style="color: #009900;">&#40;</span>wcs_intsim_thread_to_interrupt_handle<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// get its windows thread context</span>
	GetThreadContext<span style="color: #009900;">&#40;</span>wcs_intsim_thread_to_interrupt_handle<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>ctx<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// push the address we want to return to (which is wherever the RTOS thread is now)</span>
	<span style="color: #666666; font-style: italic;">// after our simulated ISR to the RTOS thread's stack</span>
	ctx.<span style="color: #202020;">Esp</span> <span style="color: #339933;">-=</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>ctx.<span style="color: #202020;">Esp</span> <span style="color: #339933;">=</span> ctx.<span style="color: #202020;">Eip</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// set the instruction pointer of the kernel thread to that of the ISR routine</span>
	ctx.<span style="color: #202020;">Eip</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>DWORD<span style="color: #009900;">&#41;</span>wcs_tick_isr<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// set context of the kernel thread, effectively overriding the instruction ptr</span>
	SetThreadContext<span style="color: #009900;">&#40;</span>wcs_intsim_thread_to_interrupt_handle<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>ctx<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// resume the kernel thread</span>
	ResumeThread<span style="color: #009900;">&#40;</span>wcs_intsim_thread_to_interrupt_handle<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>We push the current kernel thread&#8217;s instruction pointer register to the top of its stack (so that the current RTOS thread can resume execution once its ready again) and then override it with a pointer to our (naked) routine performing the save and switch context. Once the interrupt thread goes back to pending on its message queue, the kernel thread will resume and effectively handle the interrupt (again, by saving current context and loading the next RTOS thread).</p>
<div class="img-frame"><a rel="lightbox" href="/wp-content/uploads/preemptive-kernel/preemptive.png" title="Example of simulating a preemptive kernel using two Windows threads" ><span><img class="img-frame " src="/wp-content/themes/dandelion_v2.6.1/functions/timthumb.php?src=/wp-content/uploads/preemptive-kernel/preemptive.png&amp;w=650h=&amp;zc=1" alt="" /></span></a></div>
<p><h2 class="post-heading">And now some code</h2><hr class="post-heading" /><br />
The RTOS I implemented was very feature rich &#8211; it supported waiting on multiple objects, a variable tick timer (that is, a tick only occured when needed), a zero overhead heap, and many other cool things &#8211; all fully simulated. I extracted the essence of this article from that RTOS into a single C++ module (360 lines of commented code, I didn&#8217;t even attach a header) that was tested under x86 running Windows 7, compiled with VS 2008. In this example I only show the simplest form of preemption &#8211; a constant tick that time slices between two threads which are created before the kernel starts running. This is only a proof of concept &#8211; building atop of this, one can implement pretty much everything an RTOS offers (dynamic thread creation/deletion, waitable objects, timers, etc). </p>
<p><a href="/wp-content/uploads/preemptive-kernel/winContextSwitch.cpp">Download example (winContextSwitch.cpp, ~360 lines of commented code)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.pavius.net/2011/04/implementing-a-preemptive-kernel-within-a-single-windows-thread/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Getting egress interface by destination IP in VxWorks 5.x</title>
		<link>http://www.pavius.net/2011/02/getting-egress-interface-by-destination-ip-in-vxworks-5-x/</link>
		<comments>http://www.pavius.net/2011/02/getting-egress-interface-by-destination-ip-in-vxworks-5-x/#comments</comments>
		<pubDate>Thu, 17 Feb 2011 23:41:18 +0000</pubDate>
		<dc:creator>Eran Duchan</dc:creator>
				<category><![CDATA[VxWorks]]></category>
		<category><![CDATA[egress ip]]></category>
		<category><![CDATA[routing table]]></category>
		<category><![CDATA[vxworks]]></category>

		<guid isPermaLink="false">http://www.pavius.net/?p=40</guid>
		<description><![CDATA[Here&#8217;s a small code snippet that may be useful to the 20 or so VxWorks programmers left on the planet. I thought this would be much easier than it turned out to be, but after gathering code examples from here and there in the VxWorks source tree, I was able to query the routing table [...]]]></description>
			<content:encoded><![CDATA[<div class="blog-post-img"><a href="2011/02/getting-egress-interface-by-destination-ip-in-vxworks-5-x"> <img class="attachment-post_box_img wp-post-image" src="/wp-content/uploads/vxworks-route-get/header.jpg" alt="" width="640" /></a></div>
<p>Here&#8217;s a small code snippet that may be useful to the 20 or so VxWorks programmers left on the planet. I thought this would be much easier than it turned out to be, but after gathering code examples from here and there in the VxWorks source tree, I was able to query the routing table as to which interface is used for a certain egress IP address.</p>
<p>VxWorks 5.x doesn&#8217;t really have a &#8220;user&#8221; and &#8220;kernel&#8221; space, so you&#8217;re kind of inclined to directly access the routing table (like how routeShow does it) should you need routing information. Looking at the code for rtalloc, rtalloc1 and ipRouteGet shows that this is a recipe for pain. <span id="more-40"></span>Since a lot of BSD code found its way into the VxWorks networking stack, you can use standard route sockets to get routing information from your application, without worrying about tripping over locks and such. </p>
<p>In the attached example, I have a routine to get the egress interface by destination IP address. I only look at the interface information in the response, but this should serve as a good example as to how to get more information from the routing table.</p>
<p>You can download the code <a href="/wp-content/uploads/vxworks-route-get/vxGetRouteInfo.c">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pavius.net/2011/02/getting-egress-interface-by-destination-ip-in-vxworks-5-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Compiling Net-SNMP for PowerPC running Embedded Linux</title>
		<link>http://www.pavius.net/2011/02/compiling-net-snmp-for-embedded-linux-using-the-eldk/</link>
		<comments>http://www.pavius.net/2011/02/compiling-net-snmp-for-embedded-linux-using-the-eldk/#comments</comments>
		<pubDate>Thu, 17 Feb 2011 20:17:34 +0000</pubDate>
		<dc:creator>Eran Duchan</dc:creator>
				<category><![CDATA[Embedded Linux]]></category>
		<category><![CDATA[compile]]></category>
		<category><![CDATA[denx]]></category>
		<category><![CDATA[eldk]]></category>
		<category><![CDATA[embedded]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[net-snmp]]></category>
		<category><![CDATA[ppc]]></category>
		<category><![CDATA[snmp]]></category>
		<category><![CDATA[snmpd]]></category>

		<guid isPermaLink="false">http://www.pavius.net/?p=36</guid>
		<description><![CDATA[I was recently requested to get SNMPv3 up and running on a PPC board running Linux. It needed to support hardcoded views, creation/deletion of V3 USM users in runtime and allow for three security profiles: none, MD5 authentication and MD5 authentication with DES encryption. The obvious choice is to base this on Net-SNMP, but I [...]]]></description>
			<content:encoded><![CDATA[<div class="blog-post-img"><a href="2011/02/compiling-net-snmp-for-embedded-linux-using-the-eldk"> <img class="attachment-post_box_img wp-post-image" src="/wp-content/uploads/net-snmp/header.jpg" alt="" width="640" /></a></div>
<p>I was recently requested to get SNMPv3 up and running on a PPC board running Linux. It needed to support hardcoded views, creation/deletion of V3 USM users in runtime and allow for three security profiles: none, MD5 authentication and MD5 authentication with DES encryption. The obvious choice is to base this on Net-SNMP, but I first tried to use the version precompiled and included in the ELDK. By simply loading the appropriate binaries on to the target, I quickly got an SNMP agent functioning. There were two issues:</p>
<ol>
<li>The version was compiled in a certain way that took up a lot of flash space (openssl was required as an external shared library)</li>
<li>The version was pretty old &#8211; based on the 5.4.x branch</li>
</ol>
<p>For fun, I downloaded the ELDK source RPMs, unpackaged, tailored the RPM spec, rebuilt and installed it on to my ELDK library. Sure enough, I got a much smaller agent but decided I want to use the latest and greatest Net-SNMP, 5.6.1 at the time of writing. The build process below assumes you have ELDK 4.2 installed on Ubuntu. You can check out <a href="/blog/2011/01/building-uboot-linux-ppc">a recent post of mine</a> for detailed installation instructions.<span id="more-36"></span></p>
<p>Start by downloading the latest source packages from the Net-SNMP site. Extract it to a directory and open it in a terminal. We then start by setting CROSS_COMPILE, required for running ppc-linux-gcc (in my case, ppc_8xx).</p>
<pre>CROSS_COMPILE=ppc_8xx
export CROSS_COMPILE</pre>
<p>Now we can simply go ahead and configure Net-SNMP for our needs:</p>
<pre>./configure --host=ppc-linux --build=i386-pc-linux-gnu --target=ppc-denx-linux --program-prefix= --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --sysconfdir=/etc --datadir=/usr/share --includedir=/usr/include/net-snmp --libdir=/usr/lib --libexecdir=/usr/libexec --localstatedir=/var --sharedstatedir=/usr/com --mandir=/usr/share/man --infodir=/usr/share/info --with-endianness=big --enable-privacy --enable-des --enable-internal-md5 --disable-snmpv1 --without-rpm --with-openssl=internal --enable-mini-agent --with-out-transports="TCP Callback Unix Alias" --with-default-snmp-version="3" --enable-shared --with-cflags="-O2 -fsigned-char" --with-ldflags= --with-sys-location=Unknown --with-logfile=/var/log/snmpd.log --with-persistent-directory=/var/net-snmp --with-out-mib-modules=examples/ucdDemoPublic --sysconfdir=/etc --with-libwrap --with-pic --disable-embedded-perl --with-perl-modules=no --with-sys-contact=root@localhost --disable-manuals --disable-scripts --disable-mibs --disable-mib-loading --disable-deprecated</pre>
<p>There are a few important options here:</p>
<ul>
<li><span style="line-height: 18px;">host, target, build: To be honest, I&#8217;m not exactly sure why these are the required settings for these variables, but I went through a lot of trial and error and this is what generated a working output</span></li>
<li>enable-privacy, enable-des, enable-internal-md5: For authentication and encryption we need this. I am using &#8220;internal&#8221; MD5, hoping it will save a bit of space</li>
<li>with-openssl=internal: Here&#8217;s the big one. If you need to support authentication and encryption, you will need the 1.3MB OpenSSL shared object (by setting with-openssl to yes or with no value). By setting this to &#8220;internal&#8221; you compile the required functionality into the agent and do not need to have the OpenSSL shared object present on your target</li>
<li>enable-mini-agent: This seems to build less MIB support into the agent. Perhaps it does more things, but I&#8217;m not sure</li>
</ul>
<p><span style="line-height: 18px;"> </span></p>
<p>You can see the help for the rest of the options by running ./configure &#8211;help. After we configured the agent we simply need to build it:</p>
<pre>make</pre>
<p>And then install it to a temporary location</p>
<pre>make install INSTALL_PREFIX=/tmp/net-snmp-5.6.1</pre>
<p>We then copy the following files to the target</p>
<ul>
<li>/tmp/net-snmp-5.6.1/usr/lib/libnetsnmp.so.25 to /usr/libs</li>
<li>/tmp/net-snmp-5.6.1/usr/lib/libnetsnmpagent.so.25 to /usr/libs</li>
<li>/tmp/net-snmp-5.6.1/usr/lib/libnetsnmphelpers.so.25 to /usr/libs</li>
<li>/tmp/net-snmp-5.6.1/usr/lib/libnetsnmpmibs.so.25 to /usr/libs</li>
<li>/tmp/net-snmp-5.6.1/usr/sbin/snmpd to /usr/sbin (and chmod +x it)</li>
</ul>
<p>On the target, we create /usr/etc/snmp and upload an snmpd.conf file. This configuration file allows you to specify V2 communities, views, V3 users and much more. See <a href="/wp-content/uploads/net-snmp/snmpd.conf">this custom snmpd.conf</a> i made for a simple V2/V3 example.</p>
<p>Now we&#8217;re ready to run the SNMP agent on the target:</p>
<pre>snmpd</pre>
<p>All in all, this requires ~1 MB of flash. Be aware that the apps directory holds all the Net-SNMP applications (snmpget, snmpset, snmptrap, etc) &#8211; they are very small and useful (~30k).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pavius.net/2011/02/compiling-net-snmp-for-embedded-linux-using-the-eldk/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Repairing FreeNAS after a power outage (FreeNAS rebooting)</title>
		<link>http://www.pavius.net/2011/02/reviving-freenas-after-power-outage/</link>
		<comments>http://www.pavius.net/2011/02/reviving-freenas-after-power-outage/#comments</comments>
		<pubDate>Sat, 12 Feb 2011 11:39:57 +0000</pubDate>
		<dc:creator>Eran Duchan</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[ffs_blkfree]]></category>
		<category><![CDATA[freeing free block]]></category>
		<category><![CDATA[FreeNAS]]></category>
		<category><![CDATA[panic]]></category>

		<guid isPermaLink="false">http://www.pavius.net/?p=34</guid>
		<description><![CDATA[For reasons beyond me, I have a storage server set up with FreeNAS. I find it convenient to have all of my movies/music/TV shows on a PC that sees no action besides reading and writing to its drives. This weekend, while streaming a show from my storage server, the power went out. The server is [...]]]></description>
			<content:encoded><![CDATA[<div class="blog-post-img"><a href="2011/02/reviving-freenas-after-power-outage"> <img class="attachment-post_box_img wp-post-image" src="/wp-content/uploads/freenas-fsck/header.jpg" alt="" width="640" /></a></div>
<p>For reasons beyond me, I have a storage server set up with FreeNAS. I find it convenient to have all of my movies/music/TV shows on a PC that sees no action besides reading and writing to its drives. This weekend, while streaming a show from my storage server, the power went out. The server is connected directly to mains, so it went down &#8211; hard. To be fair, my Ubuntu based media center PC also died, never to recover. After a bit of troubleshooting and an annoying secondary problem, it seems to be up and stable.</p>
<p>My FreeNAS server is based on a 4 year old AMD 3200+ PC. Before setting everything up I made sure to clean the motherboard and CPU mount, applied new thermal grease on the CPU heatsink and upgraded the PSU to a Thermaltake 480W PSU &#8211; I really wanted to reduce chance of having any electrical/heat related issues that would take out the system.<span id="more-34"></span> FreeNAS was loaded on a USB drive and a single 1.5TB drive was attached to the SATA bus. The server sat alone in a closet, connected via Gigabit ethernet to my home LAN and remained there. Headless, keyboard-less and monitor-less.</p>
<p>After the outage, the server did not respond to pings. I hooked it up to my monitor and attached a keyboard. It seemed like the BIOS did not even attempt to load an OS. I checked the BIOS settings and it seemed to revert to booting from HDD. Triumphantly I changed it to boot from USB and rebooted. Nothing. I then went ahead and restored BIOS defaults and again changed to boot from USB, just to start from a clean slate seeing as <em>something</em> freaky went on with the BIOS settings. No dice.</p>
<p>I tried yanking the USB key holding FreeNAS but that showed nothing. I then yanked the SATA cable from the HDD and finally something &#8211; the BIOS seemed to print something about Nvidia boot loader agent, but again hung. I knew something had shifted so I replugged the USB drive and voila &#8211; FreeNAS loaded. I let it load again with the HDD connected and it seemed I was successful.</p>
<p><h2 class="post-heading">Plot twist: FreeNAS reboots itself every 20 minutes</h2><hr class="post-heading" /><br />
I patted myself on the back, called the wife, sat on the couch and loaded &#8220;The Wire&#8221; episode we were watching. After a few seconds, VLC crapped out indicating failure to read from file. The storage server was down again. I was smart and pessimistic enough not to disconnect the server from the monitor so I could get a glimpse of what was happening. After a bit of investigating, I saw that FreeNAS would reboot every ~15-20 minutes, claiming the following panic:</p>
<pre>panic: ffs_blkfree: freeing free block</pre>
<p>So it&#8217;s a file system issue, methinks. I then performed the following:</p>
<ol>
<li>Via the FreeNAS shell I ran &#8220;mount&#8221; to see which partition my storage mount was on (it was /dev/ad4p1)</li>
<li>Via the FreeNAS web interface, I deleted the shares on the drive and deleted it from the drive management (this does not destroy the data on the drive, just detaches it apparently). Reboot</li>
<li>Manually unmount mount in /mnt (in my case, &#8220;umount /mnt/storage1&#8243; &#8211; this depends on your setup). Reboot. At this point the partition should not be in use by FreeNAS</li>
<li>Time to fix the partition. I ran &#8220;fsck -t ufs -y /dev/ad4p1&#8243; several times, until no errors appeared. Reboot</li>
<li>Via the FreeNAS web interface, added the drive (making sure pre-formatted was set to UFS). Re-added the share</li>
</ol>
<p>That&#8217;s it. FreeNAS is up, running and stable&#8230; until the next power outage that is.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pavius.net/2011/02/reviving-freenas-after-power-outage/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Building and deploying U-Boot and Linux for a PPC8xx board</title>
		<link>http://www.pavius.net/2011/01/building-uboot-linux-ppc/</link>
		<comments>http://www.pavius.net/2011/01/building-uboot-linux-ppc/#comments</comments>
		<pubDate>Tue, 11 Jan 2011 17:07:38 +0000</pubDate>
		<dc:creator>Eran Duchan</dc:creator>
				<category><![CDATA[Embedded Linux]]></category>
		<category><![CDATA[bringup]]></category>
		<category><![CDATA[embedded]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[ppc8xx]]></category>
		<category><![CDATA[u-boot]]></category>
		<category><![CDATA[uboot]]></category>

		<guid isPermaLink="false">http://pavius.dreamhosters.com/?p=28</guid>
		<description><![CDATA[This post describes the steps required for setting up an Ubuntu based compilation and debugging environment for U-Boot and Linux 2.6 w/a JFFS2 filesystem on a custom PPC board, using an Abatron BDI3000. It mostly discusses the environment and doesn&#8217;t dive too much as to how to customize the packages for your specific board (this [...]]]></description>
			<content:encoded><![CDATA[<div class="blog-post-img"><a href="2011/01/building-uboot-linux-ppc"> <img width="640" src="/wp-content/uploads/uboot-linux-ppc8xx/header.jpg" class="attachment-post_box_img wp-post-image" alt="" title="" /></a></div>
<p>This post describes the steps required for setting up an Ubuntu based compilation and debugging environment for U-Boot and Linux 2.6 w/a JFFS2 filesystem on a custom PPC board, using an Abatron BDI3000. It mostly discusses the environment and doesn&#8217;t dive too much as to how to customize the packages for your specific board (this is the hard part, but also extremely board specific). While you will probably not follow this guide from start to finish, it serves as a reference for what is the minimal amount of work required to build U-Boot and Linux for a PPC8xx board and a supplement to the <a href="http://www.denx.de/wiki/DULG/WebHome">DENX DULG</a>, which is a must read.</p>
<p>It assumes that Ubuntu is already installed on the station, but nothing else. On the host side we mostly need the ELDK – a single package that contains all the cross tools needed (compiler, linker, debugger, tools to generate a file system, etc.).<span id="more-28"></span></p>
<p>A basic U-Boot/Linux target requires four things:</p>
<ul class="bullet_arrow2">
<li> A U-Boot binary (u-boot.bin) generated by customizing the U-Boot sources for your board, compiled using a cross-compiler (ppc_8xx-gcc in our case) and burned to the correct offset in the flash</li>
<li><span style="line-height: 19px;"> Linux image (uImage) generated by compiling the untouched Linux sources</span></li>
<li><span style="line-height: 19px;"> A Flat Device Tree BLOB (.dtb file), generated by compiling (using a specialized compiler) a textual DTS file which describes busses, offsets and devices of the target board</span></li>
<li><span style="line-height: 19px;"> A Root file system containing all the files we&#8217;d like to appear on the target once it&#8217;s up, packed into a single file. This file is generated by packaging up a directory from the ELDK which contains all the tools compiled for the architecture using the appropriate file system maker (in our case, mkfs.jffs2).</span></li>
</ul>
<h2 class="post-heading">Step 1: Getting the sources</h2><hr class="post-heading" />
<p>In this step we install git (the source control system), eldk (the development environment), U-Boot (the bootloader) and Linux (the OS). Start by getting eldk 4.2 for PPC (iso) from <a href="http://www.denx.de/wiki/view/DULG/ELDKAvailability">here</a> (The file is under /pub/eldk/4.2/ppc-linux-x86/ppc-2008-04-01.iso). Keep in mind that this may be very slow as the file is 1.9 GB; I used <a href="http://www.getright.com/">GetRight</a> on windows to pull the file from all the mirrors concurrently.</p>
<p>Create a working directory in your home directory:</p>
<pre>mkdir ~/dev
cd ~/dev</pre>
<p>Get git:</p>
<pre>sudo apt-get install git-core</pre>
<p>Get U-Boot sources:</p>
<pre>git clone git://git.denx.de/u-boot.git u-boot/</pre>
<p>Get Linux sources:</p>
<pre>git clone git://git.denx.de/linux-2.6-denx.git linux-2.6-denx/</pre>
<p><h2 class="post-heading">Step 2: Installing the ELDK</h2><hr class="post-heading" /><br />
Create an installation directory under your working directory (e.g. ~/dev/eldk)</p>
<pre>mkdir eldk
cd eldk</pre>
<p>Create a mount point for the ELDK installation CD and mount it (prepend the path of the iso to the file):</p>
<pre>sudo mkdir /mnt/eldk-inst
sudo mount -o loop,exec ppc-2008-04-01.iso /mnt/eldk-inst/</pre>
<p>Install the eldk for the ppc8xx architecture</p>
<pre>/mnt/eldk-inst/install ppc_8xx</pre>
<p>Add eldk to path by appending the following in ~/.bashrc using a text editor of choice (make sure to show hidden files). After this is done, make sure to re-open a terminal window for the next steps:<br />
PATH=$PATH:~/dev/eldk/usr/bin:~/dev/eldk/bin<br />
export PATH</p>
<p>Test this by running the following in your dev directory:</p>
<pre>ppc_8xx-gcc</pre>
<p>You should see the standard gcc “no input files” error.</p>
<p><h2 class="post-heading">Step 3: Preparing a JFFS2 filesystem</h2><hr class="post-heading" /><br />
The ELDK contains a basic yet functional file system that we can use. It is packaged as a ramdisk image and we need to extract it so that we can build a JFFS2 image.</p>
<p>Strip the prepared ramdisk of its 64 byte header, revealing a gzipped file. Unzip it to receive ramdisk_image</p>
<pre>cd ~/dev/eldk/ppc_8xx/images
dd if=uRamdisk bs=64 skip=1 of=ramdisk.gz</pre>
<p>Mount the image and give everyone access/execute permissions to it</p>
<pre>sudo mkdir /mnt/rootfs-inst
sudo mount -o loop ramdisk_image /mnt/rootfs-inst
sudo chmod -R 777 /mnt/rootfs-inst/</pre>
<p>Generate the JFFS2 image assuming a sector size of 128KB (0&#215;20000), in this case</p>
<pre>mkfs.jffs2 -b -r /mnt/rootfs-inst -e 0x20000 -o image.jffs2</pre>
<p><h2 class="post-heading">Step 4: Finishing up environment installation</h2><hr class="post-heading" /><br />
The development station requires a TFTP server for two reasons: the BDI3000 TFTPs a configuration file each time it loads and U-Boot will fetch the Linux images via TFTP once it is burnt to flash. We must therefore install a TFTP server and set up its directories.</p>
<p>First, we’ll install atftpd:</p>
<pre>sudo apt-get install atftpd
sudo gedit /etc/default/atftpd (modify to USE_INETD=FALSE)
sudo invoke-rc.d atftpd start
sudo chmod 777 /srv/tftp</pre>
<p>We then create three directories @ /srv/tftp:</p>
<pre>mkdir /srv/tftpd/u-boot
mkdir /srv/tftpd/linux
mkdir /srv/tftpd/bdi3000</pre>
<p>Configure the BDI’s server IP address. See BDI documentation for more info how to do this.</p>
<p><h2 class="post-heading">Step 5: Compiling U-Boot to receive a burnable u-boot.bin</h2><hr class="post-heading" /><br />
Customize U-Boot for your board. For a custom board with SDRAM and 8MB Flash, I had to:</p>
<ul>
<li>Create a directory under /board/my_board and have a Makefile, config.mk, u-boot.lds and my_board.c. You can copy these files from the standard ep8xx board</li>
<li>my_board.c implemented the following functions:
<ul>
<li>checkboard: Just printed a banner</li>
<li>initdram: Initialize the SDRAM</li>
<li>board_poweroff: Reboot hook (didn&#8217;t implement anything here)</li>
<li>ft_board_setup: Fixed up the FTD BLOB passed to Linux with information gathered by U-Boot</li>
</ul>
</li>
<li>Add a header file under include/configs/my_board.h with all the preprocessor directives. Again, you can reference the standard ep8xx board, but make sure to define CONFIG_OF_LIBFDT and CONFIG_OF_BOARD_SETUP. Otherwise Linux will not boot because it doesn&#8217;t receive the FDT BLOB</li>
<li>Add the board to the main Makefile (you should be able to easily understand using ep8xx as an example)</li>
</ul>
<p>Clean, just to make sure</p>
<pre>make distclean
make clean</pre>
<p>And then compile it</p>
<pre>make my_board
make</pre>
<p><h2 class="post-heading">Step 6: Compiling Linux</h2><hr class="post-heading" /><br />
Start by installing ncurses, required for menuconfig</p>
<pre>sudo apt-get libncurses5-dev</pre>
<p>At this point you will have to customize Linux. For PPC this mostly means creating a compilable device tree file (with a .dts extension) which describes the offsets of the core peripherals and such (instead of instantiating drivers in code). This is not trivial and is yet another syntax/structure to learn, but at least you have examples in the form of dts files for existing boards. In addition, you will also have to create a default configuration in arch/powerpc/configs, a custom platform in arch/powerpc/platforms (which will, at least, initialize I/O pins) and modify arch/powerpc/platforms/Kconfig + arch/powerpc/platforms/Makefile to support your new platform. Simply go by example of existing boards and check out <a href="https://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdf">this PDF</a>.</p>
<p>Build Linux and the FDT BLOB (DTB file)</p>
<pre>make ARCH=powerpc CROSS_COMPILE=ppc_8xx- my_board_defconfig
make ARCH=powerpc CROSS_COMPILE=ppc_8xx- uImage
make ARCH=powerpc CROSS_COMPILE=ppc_8xx- my_board.dtb</pre>
<h2 class="post-heading">Step 7: Burning and configuring U-Boot</h2><hr class="post-heading" />
<p>The following sections assume the following offsets: Flash starts at 0xFF800000 which is where the Linux kernel resides (until 0xFF9DFFFF), the DTB file resides at 0xFF9E0000 until 0xFF9FFFFF, the JFFS2 filesystem image resides at 0xFFA00000. Finally, U-Boot resides at 0xFFF00000.</p>
<p>Set up your BDI with a configuration script that will allow you to attach to the board and erase its flash. Define the sectors on which u-boot will reside so that the erase command will know what to delete. Copy u-boot.bin (from ~/dev/u-boot) to /srv/tftp/u-boot and then telnet to the bdi.</p>
<pre>reset
erase
prog 0xfff00000</pre>
<p>Open a serial connection to the target. Setup u-boot to auto-load the kernel at 0xFF800000 and pass the DTB @ 0xFF9E0000.</p>
<pre>setenv ethaddr 00:e0:6f:00:00:01
setenv ipaddr [target-ip-address]
setenv serverip [your-pc-ip-address]
setenv bootargs root=/dev/mtdblock2 rw rootfstype=jffs2
setenv bootcmd bootm 0xff800000 - 0xff9e0000
setenv bootdelay 3
saveenv</pre>
<p><h2 class="post-heading">Step 8: Burning Linux, the DTB and the Root filesystem</h2><hr class="post-heading" /><br />
Copy image.jffs2 created earlier and uImage, my_board.dtb from arch/powerpc/boot to the /srv/tftp/linux directory</p>
<p>Using the U-Boot console, download the images to RAM via tftp. After each download, note the size printed by u-boot in hex: Bytes transferred = 1284822 (139ad6 hex). You will need this for the next step.</p>
<pre>tftp 0x100000 /linux/image.jffs2
tftpboot 0x400000 /linux/uImage
tftpboot 0x800000 /linux/my_board.dtb</pre>
<p>Burn the images to the flash</p>
<pre>erase 0xffa00000 0xffcfffff
erase 0xff800000 0xff9fffff
cp.b 0x400000 0xff800000 [linux-size-in-hex, e.g. 139ad6]
cp.b 0x800000 0xff9e0000 [dtb-size-in-hex]
cp.b 0x100000 0xffa00000 [jffs2-size-in-hex]
</pre>
<p>Power cycle the board &#8211; Linux should be up.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pavius.net/2011/01/building-uboot-linux-ppc/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Rotary encoder based cooking timer</title>
		<link>http://www.pavius.net/2010/02/rotary-encoder-based-cooking-timer/</link>
		<comments>http://www.pavius.net/2010/02/rotary-encoder-based-cooking-timer/#comments</comments>
		<pubDate>Sat, 20 Feb 2010 18:10:51 +0000</pubDate>
		<dc:creator>Eran Duchan</dc:creator>
				<category><![CDATA[Microcontrollers]]></category>
		<category><![CDATA[pic]]></category>
		<category><![CDATA[quadrature]]></category>
		<category><![CDATA[rotary encoder]]></category>
		<category><![CDATA[seven segment display]]></category>

		<guid isPermaLink="false">http://pavius.dreamhosters.com/?p=8</guid>
		<description><![CDATA[Continuing my experimentations with cooking timer user interfaces, I stumbled upon a cute little rotary encoder on Sparkfun. It immediately looked like a good match for the project. The thing is that all cooking timers I’ve seen have either a simplistic interface requiring many clicks to set the time (like clicking the “minutes” button 50 [...]]]></description>
			<content:encoded><![CDATA[<div class="blog-post-img"><a href="2010/02/rotary-encoder-based-cooking-timer"> <img width="640" src="/wp-content/uploads/rotary-encoder-timer/header.jpg" class="attachment-post_box_img wp-post-image" alt="" title="" /></a></div>
<p>Continuing my experimentations with cooking timer user interfaces, I stumbled upon a cute little rotary encoder on Sparkfun. It immediately looked like a good match for the project. The thing is that all cooking timers I’ve seen have either a simplistic interface requiring many clicks to set the time (like clicking the “minutes” button 50 times) or a complex keypad with way too many buttons.</p>
<p>At first I thought I&#8217;d need 2 axes (axis 1 would increment by 1 minute and the other axis by 15 minutes) but fiddling around with the trackball showed me that it was not necessary; that I&#8217;d just need one axis with tactile feedback (that is, a clicky switch rather than a smooth flowing motion of the controller) and some selection mechanism to switch between 1 and 15 minutes.<span id="more-8"></span></p>
<p>The Sparkfun rotary encoder fit the bill – 12 steps for full rotation and clickable! Perfect. I wired up the encoder on the breadboard, wrote the software and then fabricated two one layer PCBs.</p>
<p><h2 class="post-heading">The Hardware</h2><hr class="post-heading" /><br />
<div class="img-frame"><a rel="lightbox" href="/wp-content/uploads/rotary-encoder-timer/timer-pic.jpg" title="The finished rotary encoder based timer" ><span><img class="img-frame alignright" src="/wp-content/themes/dandelion_v2.6.1/functions/timthumb.php?src=/wp-content/uploads/rotary-encoder-timer/timer-pic.jpg&amp;w=h=115&amp;zc=1" alt="" /></span></a></div>The schematic is fairly straightforward – a PIC18F2525 sits in the middle connected to the rotary encoder (gray code and button), 3 indication LEDs and a buzzer (link to the schematic at the end of the article). The main board connects to the seven segment display mezzanine via two connectors. This board is not, in any way, efficient power wise &#8211; it sucks about as much energy as humanly possible.</p>
<h6>4 digit Seven segment display</h6>
<p>Another Sparkfun gem is the integrated 4 digit seven segment display. The 4 digits are internally connected and there’s even a colon in there – we save a LOT of nets and do not need to flip the 3rd digit to create a colon as there is a dedicated colon segment. The display isn’t huge, measuring in at 4 centimeters across, but will suffice for this test project. Hooking this up to the uC is very standard so I won’t dive into details. The only thing worth noting is that we need to wire up the colon anode to VCC and the cathode to the uC for controlling, holding it at logic high. When we want to light it up we sink the current on the uC by setting the cathode to logic low. You could and should ramp up/PWM this line so as to have consistent brightness with the multiplexed digits (i don&#8217;t do it in this project).<br />
<div class="img-frame"><a rel="lightbox" href="/wp-content/uploads/rotary-encoder-timer/ssd.jpg" title="The seven segment display from Sparkfun" ><span><img class="img-frame " src="/wp-content/themes/dandelion_v2.6.1/functions/timthumb.php?src=/wp-content/uploads/rotary-encoder-timer/ssd.jpg&amp;w=650h=&amp;zc=1" alt="" /></span></a></div></p>
<h6>Clickable rotary encoder</h6>
<p>The rotary encoder from Sparkfun gives two inputs: rotation (CW/CCW) and button click. The rotation interfaces takes the form of a standard gray code output: two channels connected to the uC input pins (w/external or internal pull ups) and ground. The difference between this encoder and the trackball from my previous project is that this is a purely mechanical interface, as opposed to a digital interface with the ALPS trackball. This means that while we received a perfectly filtered gray code signal from the IC on the ALPS, here we receive gray code directly from the mechanical rotation. Each rotation simply connects the channels to ground shifted by a quarter phase. In 99% of the cases we receive a good signal, but those extra 1% bounces need handling. We will see the waveforms in a bit.<br />
<div class="img-frame"><a rel="lightbox" href="/wp-content/uploads/rotary-encoder-timer/rotary-enc.jpg" title="The rotary encoder from Sparkfun" ><span><img class="img-frame " src="/wp-content/themes/dandelion_v2.6.1/functions/timthumb.php?src=/wp-content/uploads/rotary-encoder-timer/rotary-enc.jpg&amp;w=650h=&amp;zc=1" alt="" /></span></a></div><br />
The integrated button is as simple as it gets – just like any other button pulled high and shoved into the uC input.</p>
<h2 class="post-heading">The Software</h2><hr class="post-heading" />
<h6>Rotary encoder state machine</h6>
<p>In my previous trackball project I needed to receive an event whenever the trackball moved. This was achieved very easily by simply analyzing the gray code and detecting valid gray code transitions. The difference here is that we don’t want to react whenever a bit change occurs, rather when a complete, valid cycle occurs. This cycle indicates that the user has performed one “click” on the control (there are 12 such clicks in a complete rotation). By detecting such valid cycles we filter out two unwanted events:<br />
<div class="bullet_arrow2"></p>
<li>Mechanical bounces (see rightmost waveform below)</li>
<li>The user overshooting and performing an extra “half” click (see middle waveform below)</li>
<p></div>The software needs to look for two certain valid 4 step flows: a CW click and a CCW click, as shown in the leftmost waveform.</p>
<div style="width: 650px;">
<div style="float: left; width: 215px;"><div class="img-frame"><a rel="lightbox" href="/wp-content/uploads/rotary-encoder-timer/waveform-valid-cycle.jpg" title="A valid cycle waveform" ><span><img class="img-frame alignright" src="/wp-content/themes/dandelion_v2.6.1/functions/timthumb.php?src=/wp-content/uploads/rotary-encoder-timer/waveform-valid-cycle.jpg&amp;w=205h=&amp;zc=1" alt="" /></span></a></div></div>
<div style="float: left; width: 215px;"><div class="img-frame"><a rel="lightbox" href="/wp-content/uploads/rotary-encoder-timer/waveform-half-cycle.jpg" title="Waveform when turning the rotary encoder not all the way" ><span><img class="img-frame alignright" src="/wp-content/themes/dandelion_v2.6.1/functions/timthumb.php?src=/wp-content/uploads/rotary-encoder-timer/waveform-half-cycle.jpg&amp;w=205h=&amp;zc=1" alt="" /></span></a></div></div>
<div style="float: left; width: 215px;">
<div style="float: left; width: 215px;"><div class="img-frame"><a rel="lightbox" href="/wp-content/uploads/rotary-encoder-timer/waveform-noise.jpg" title="Waveform demonstrating mechanical noise" ><span><img class="img-frame alignright" src="/wp-content/themes/dandelion_v2.6.1/functions/timthumb.php?src=/wp-content/uploads/rotary-encoder-timer/waveform-noise.jpg&amp;w=205h=&amp;zc=1" alt="" /></span></a></div></div>
<p><br style="clear: left;" />
</div>
<p>Normally, both channels are pulled up and sit there at logic 1. The CW flow starts by the first channel going to 0 followed by the second channel. The first channel then goes back up to 1 and so does the second. Any deviation of this flow should be filtered out, but mechanical bounces need not cause the motion to be ignored. To fulfill these requirements, I implement this using a two 3 bit “shift register” variables and a simple state machine.</p>
<p>The 3 bit shift registers hold the last 3 polled values of each channel. The polling rate must be fast enough such that 3 polls indicate a stable logic value (you can calculate the polling time required by measuring the shortest bit cycle you can and then diving this by at least 5 – for example if the channel bit is 1ms long when you turn the knob as fast as you can, you should set your polling to at most 200uS). The shift register value is then fed into a pattern matcher – this simply compares the value to either 111 (stable 1) or 000 (stable 0) at any given time. If a match occurs, a bit is appended to the value of the shift register – 0 for channel 0 and 1 for channel 1 (for example, if channel 1 has detected a transition to 0, the new value will be 1000, uniquely identifying an event that channel 1 has transitioned to 0). This new value is then fed into a state machine looking for a 4 consecutive values indicating the 4 step valid flow.</p>
<p><div class="img-frame"><a rel="lightbox" href="/wp-content/uploads/rotary-encoder-timer/sw-module-rotary-enc.jpg" title="Decoding the quadrature encoding flow into direction" ><span><img class="img-frame " src="/wp-content/themes/dandelion_v2.6.1/functions/timthumb.php?src=/wp-content/uploads/rotary-encoder-timer/sw-module-rotary-enc.jpg&amp;w=650h=&amp;zc=1" alt="" /></span></a></div><br />
Let’s understand this by looking at how I detect the CW flow above. At first both channels are at 1 so the shift register value is always 111 for both channels. Since we want to detect a stable transition to 0, we set the search pattern for both channels to 000. 3 consecutive polls equal to 0 satisfy the requirements of debouncing mechanical spikes. Once channel 0 goes to 0 for more than 3 polling cycles, the pattern match occurs and the value is fed to the appending mechanism which appends 0 (for channel 0). This value is then fed into the state machine which sees that it indicates the first step of the 4 step flow (channel 0 went down to zero).</p>
<p>The pattern matching for channel 0 is then set to 111 (we want to know when the channel goes back to 1) and the state machine is set to expect the next step: 1000 (channel 1 goes down to 0). In a valid flow channel 1 goes down to zero, the pattern match occurs, 1 is appended to the shift register and the value is fed to the state machine. The search pattern for channel 1 is then changed to 111 and the state machine is set to expect the next step: channel 1 goes back up to 1.</p>
<p>This flow continues until the entire flow occurs correctly. If at any point something is done in the wrong order, the entire state machine and pattern matching resets. This mechanism filters out any “half cycles” performed by the user. Only when the user clicks the rotary to the next notch will the above flow occur. This state machine is written in quadenc.c: quadenc_isr().</p>
<h6>Seven segment display</h6>
<p>Operating the 4 digit SSD is exactly the same as operating 4 separate seven segments – you select a digit via a transistor, illuminate the desired segments, pause, select next digit and repeat. There are tons of tutorials on seven segments out there so I won’t dive into details. The only thing worth mentioning here is that in my implementation I do two obvious things:</p>
<div class="img-frame"><a rel="lightbox" href="/wp-content/uploads/rotary-encoder-timer/sw-module-ssd.jpg" title="Updating the seven segment display" ><span><img class="img-frame " src="/wp-content/themes/dandelion_v2.6.1/functions/timthumb.php?src=/wp-content/uploads/rotary-encoder-timer/sw-module-ssd.jpg&amp;w=650h=&amp;zc=1" alt="" /></span></a></div>
<ol>
<li>Whenever I want to display a number I modify a RAM array containing 4 bytes – each byte representing a digit and each bit representing the appropriate segment (the position into the byte is the position of the segment in the I/O port). Doing this does not affect the value displayed to the user &#8211; <strong>it&#8217;s all done in RAM</strong> &#8211; see sseg.c: sseg_setDisplay().</li>
<li>A timer interrupt (shared with the rotary encoder polling mechanism) is set to occur ever X interval (a few milliseconds is fine). When the interrupt is raised I load the next byte (of the 4 bytes modified by the application) into the port. Can’t get any shorter than that. See sseg.c: sseg_isr().</li>
</ol>
<p>The user interface is a standard state machine driven user interface. The video below has a short walkthrough of the interface. As such, I’ll focus on the button event handling mechanism because this is somewhat reusable over projects.</p>
<p><div class="img-frame"><a rel="lightbox" href="/wp-content/uploads/rotary-encoder-timer/sw-module-buttons.jpg" title="UI state machine" ><span><img class="img-frame " src="/wp-content/themes/dandelion_v2.6.1/functions/timthumb.php?src=/wp-content/uploads/rotary-encoder-timer/sw-module-buttons.jpg&amp;w=650h=&amp;zc=1" alt="" /></span></a></div><br />
Just like for every mechanical button, software debouncing is required. This is done by polling the input pin every X ms and shifting this into a 3 bit shift register (no interrupt is used). Once a stable pattern is detected (either 000 for button down, 111 for button up) we can handle this event. However, our timer exports a few cases for the user:<br />
<div class="bullet_arrow2"></p>
<li>Single click: pausing an active timer or switching between 1 and 15 minute intervals</li>
<li>Double click: Reseting the timer</li>
<li>Long press: Start a timer</li>
<li>Press and turn: Select a timer</li>
<p></div>This requires some code to handle, done in a state machine separate from the user state machine (see ui.c: ui_checkButtonEvent()). The outputted events from this button handling machine are fed into user interface to actually perform the desired event.</p>
<p><h2 class="post-heading">Video demonstration and waveform explanation</h2><hr class="post-heading" /><br />
The following video gives an overview of the timer user interface (interesting unto itself) and then at just over five minutes in shows waveforms for working with the rotary encoder.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="650" height="385" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/U7rBVb50GHM?fs=1&amp;hl=en_US" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="650" height="385" src="http://www.youtube.com/v/U7rBVb50GHM?fs=1&amp;hl=en_US" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h2 class="post-heading">Related Downloads</h2><hr class="post-heading" />
<ul>
<li>Schematics in <a href="/wp-content/uploads/rotary-encoder-timer/rotary-timer-sch.7z">Eagle</a> and images (<a href="/wp-content/uploads/rotary-encoder-timer/timer-main-sch.png">main board schematic</a>, <a href="/wp-content/uploads/rotary-encoder-timer/timer-ssegmez-sch.png">display mezzanine board schematic</a>)</li>
<li>Corrected <a href="/wp-content/uploads/rotary-encoder-timer/sparkfun-4digit-sseg.lbr">Sparkfun 4 digit seven segment display eagle part</a> (not part of the Sparkfun library, but imported from a Sparkfun project and fixed package)</li>
<li><a href="/wp-content/uploads/rotary-encoder-timer/rotary-timer-src-001.7z">Full source</a></li>
<li><a href="/wp-content/uploads/rotary-encoder-timer/rotary-timer-hex.7z">Hex</a> file</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.pavius.net/2010/02/rotary-encoder-based-cooking-timer/feed/</wfw:commentRss>
		<slash:comments>31</slash:comments>
		</item>
		<item>
		<title>Video Review: Dremel 220-01 vs. Proxxon Micromot MB 140/S</title>
		<link>http://www.pavius.net/2010/02/dremel-220-vs-proxxon-mb140s/</link>
		<comments>http://www.pavius.net/2010/02/dremel-220-vs-proxxon-mb140s/#comments</comments>
		<pubDate>Mon, 15 Feb 2010 18:35:29 +0000</pubDate>
		<dc:creator>Eran Duchan</dc:creator>
				<category><![CDATA[Hardware tools]]></category>
		<category><![CDATA[dremel]]></category>
		<category><![CDATA[drill bits]]></category>
		<category><![CDATA[drilling pcbs]]></category>
		<category><![CDATA[mb 140/s]]></category>
		<category><![CDATA[proxxon]]></category>

		<guid isPermaLink="false">http://pavius.dreamhosters.com/?p=4</guid>
		<description><![CDATA[Started fabricating PCBs at home using the toner transfer method and needed to find a way to drill them, as I am still mostly using through hole parts. Since I was pleased with my Dad&#8217;s dremel 300, I thought it would be a good idea to get one for myself along with a Dremel 220-01 [...]]]></description>
			<content:encoded><![CDATA[<div class="blog-post-img"><a href="2010/02/dremel-220-vs-proxxon-mb140s/"> <img width="640" src="/wp-content/uploads/proxxon-review/header.jpg" class="attachment-post_box_img wp-post-image" alt="" title="" /></a></div>
<p>Started fabricating PCBs at home using the toner transfer method and needed to find a way to drill them, as I am still mostly using through hole parts. Since I was pleased with my Dad&#8217;s dremel 300, I thought it would be a good idea to get one for myself along with a Dremel 220-01 (220) drill stand. It took me a few minutes of painful work with the stand to realize just how bad it is for the job &#8211; it flexes, it&#8217;s plasticy and it&#8217;s an insult to Dremel users.</p>
<p>I got a tip to check out the Proxxon Micromot MB 140/s and IB/E, which costed me dearly. I was blown away by how stable it was &#8211; felt like I was working with a surgical tool. To make a long winded youtube video short &#8211; the Dremel is bad for drilling PCBs and the Proxxon Micromot MB 140/S and IB/E are good. I got my solid carbide bits from <a href="http://www.bitguy1.com/" target="_blank">BitGuy1</a> and was very pleased with the service and the bits themselves (they are used, but plentiful &#8211; good for amateurs like myself). He has many bits unlisted &#8211; just ask him if you can&#8217;t see what you&#8217;re looking for.<span id="more-4"></span></p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="595" height="380" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/1JyTf1tJXXo?fs=1&amp;hl=en_US" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="645" height="380" src="http://www.youtube.com/v/1JyTf1tJXXo?fs=1&amp;hl=en_US" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>Double click the video above to see in glorious HD.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pavius.net/2010/02/dremel-220-vs-proxxon-mb140s/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

