<?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-6448756203283676481</id><updated>2012-01-27T20:25:38.684+08:00</updated><category term='Ubuntu Linux svn subversion apache trac'/><category term='10.04 trac'/><category term='Ubuntu'/><category term='redmine'/><category term='mysql'/><category term='Ubuntu Samba Linux'/><title type='text'>Binghua Duan's Linux &amp; Windows CE Blog</title><subtitle type='html'>This blog will post some of my technical articles about Linux &amp;amp; Windows CE. Related topics are the kernel, memory, storage device, file system &amp;amp; Power Management...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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>18</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6448756203283676481.post-250946639801718824</id><published>2011-03-04T10:03:00.000+08:00</published><updated>2011-03-04T10:03:21.010+08:00</updated><title type='text'>Best Practice to Make Linux/Android Filesystem Robust</title><content type='html'>&lt;div class="blog-body"&gt;       &lt;h2 id="Introduction"&gt;Introduction&lt;a class="anchor" href="http://10.125.4.34/trac/linux/blog/linuxfs_stability#Introduction" title="Link here"&gt; ¶&lt;/a&gt;&lt;/h2&gt;There is a common concern in Linux-based design: the buffering of  filesystem writes is very good for performance, but may cause the  buffered data to be lost and so filesystem corruption when the system go  down unexpectedly. &lt;br /&gt;This documents presents some solutions you can take to make your Linux-based system perform more robustly. &lt;br /&gt;&lt;h2 id="a1.UseaRead-OnlyPartitionforRootFilesystem"&gt;1. Use a Read-Only Partition for Root Filesystem&lt;a class="anchor" href="http://10.125.4.34/trac/linux/blog/linuxfs_stability#a1.UseaRead-OnlyPartitionforRootFilesystem" title="Link here"&gt; ¶&lt;/a&gt;&lt;/h2&gt;The simplest solution to avoiding power failures during writes is to  avoid all writes - files that don't to be modified should be kept on a  partition that is mounted read-only. In most cases (not include NAND  flash device) it means that there will be no modifications to the entire  partition, and as a result there is no risk of corruption. If local  data writing is required, an extra read-write partition can be  established for that purpose only. With this setup, Even in worst-case,  we can still ensure system will boot correctly. &lt;br /&gt;In Android platform, there're several options to use read-only partitions: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Root filesystem as ramdisk and Android system partition as read-only partition. &lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Root filesystem and Android system files are in a same read-only partition. &lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Root filesystem and Android system files are in separate read-only partition. &lt;/li&gt;&lt;/ul&gt;Which option to use depends on the image size of the root filesystem.  Ramdisk can only hold small rootfs, and a too large partition is not  convenient to do upgrading. &lt;br /&gt;&lt;h2 id="a2.UsetheRightFilesystemforRead-writepartitions"&gt;2. Use the Right Filesystem  for Read-write partitions&lt;a class="anchor" href="http://10.125.4.34/trac/linux/blog/linuxfs_stability#a2.UsetheRightFilesystemforRead-writepartitions" title="Link here"&gt; ¶&lt;/a&gt;&lt;/h2&gt;Linux offers many many filesystems, such as jffs2, yaffs2 and ubifs for  flash devices, ext2, ext3, ext4 and btrfs for disk-like devices. &lt;br /&gt;If the Linux-based system (i.e. Android platform) is booting from a  SD/MMC card or managed NAND, the ext3 or ext4 is a good choice. &lt;br /&gt;The &lt;strong&gt;ext3&lt;/strong&gt; or &lt;strong&gt;third extended filesystem&lt;/strong&gt; (wiki: &lt;a class="ext-link" href="http://en.wikipedia.org/wiki/Ext3"&gt;&lt;span class="icon"&gt;&amp;nbsp;&lt;/span&gt;http://en.wikipedia.org/wiki/Ext3&lt;/a&gt;)  is a journaled file system that is commonly used by Linux kernel. Its  main advantage over ext2 is journaling which improves reliability and  eliminates the need to check the file system after an unclean shutdown.  The ext4 is its successor which has many extensions and performance  improvements but also brings more data loss probabilities to be paid  more attention. &lt;br /&gt;Starting from Android-2.3 (Gingerbread), many Android devices are going  to be moving from YAFFS to the ext4 filesystem according to the post on  Google official Android developer blog. (&lt;a class="ext-link" href="http://android-developers.blogspot.com/2010/12/saving-data-safely.html"&gt;&lt;span class="icon"&gt;&amp;nbsp;&lt;/span&gt;http://android-developers.blogspot.com/2010/12/saving-data-safely.html&lt;/a&gt;) &lt;br /&gt;With the ext3/4 filesystem, system crashes or power loss are far less  likely to make system become corrupted because of the journaling design. &lt;br /&gt;&lt;ul&gt;&lt;li&gt;One of the ext3 features to be noted is that by default, ext3  will commit changes to its journal every 5 seconds. So, in general, 5  seconds worth of writes might be lost as the result of a system crash or  power loss. The value can be tuned. &lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;One feature to be noted in ext4 is the delayed  allocation which means that the filesystem tries to delay the allocation  of physical disk blocks for written data as long as possible. This  policy brings some important performance benefits. Many files are  short-lived; delayed allocation can keep the system from writing  fleeting temporary files to disk at all.  And, for longer-lived files,  delayed allocation allows the kernel to accumulate more data and to  allocate the blocks for data contiguously, speeding up both the write  and any subsequent reads of that data. However, this also brings more  data loss probabilities. &lt;/li&gt;&lt;/ul&gt;There are some sysctl variables to shorten the system’s writeback time and so as to reduce the data loss possibility: &lt;br /&gt;&lt;pre class="wiki"&gt;/proc/sys/vm/dirty_expire_centiseconds&lt;br /&gt;/proc/sys/vm/dirty_writeback_centiseconds&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;The first variable controls how long written data can sit  in the page cache before it’s considered “expired” and queued to be  written to disk; it defaults to 30 seconds. &lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;The second variable controls how ofter the &lt;i&gt;pdflush&lt;/i&gt; process wakes up to actually flush expired data to disk; it defaults to 5 seconds. &lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Lowering these values will cause the system to flush  data to disk more aggressively, with a cost in the form of reduced  performance. &lt;/li&gt;&lt;/ul&gt;&lt;h2 id="a3.UseRightSolutionWhenDevelopingApplications"&gt;3. Use Right Solution When Developing Applications&lt;a class="anchor" href="http://10.125.4.34/trac/linux/blog/linuxfs_stability#a3.UseRightSolutionWhenDevelopingApplications" title="Link here"&gt; ¶&lt;/a&gt;&lt;/h2&gt;The final solution to this problem is to fix the applications which are  expecting the filesystem to provide more guarantees than it really is. &lt;br /&gt;&lt;ul&gt;&lt;li&gt;Application developer should keep in mind that data doesn’t actually consistently reach the storage media when &lt;i&gt;write()&lt;/i&gt; or even &lt;i&gt;close()&lt;/i&gt; is called. &lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Applications which want to be sure that their critical data have been committed to the media can use the &lt;strong&gt;fsync&lt;/strong&gt;() system call; that can be slow, so be careful not to call it carelessly. &lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;In Android application, if you just use &lt;strong&gt;&lt;a class="missing wiki" href="http://10.125.4.34/trac/linux/wiki/SharedPreferences" rel="nofollow"&gt;SharedPreferences?&lt;/a&gt;&lt;/strong&gt; or &lt;strong&gt;SQLite&lt;/strong&gt;, you don't need to worry about the data loss, because Android has already used fsync() to do the right thing about buffering. &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-250946639801718824?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/250946639801718824/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=250946639801718824' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/250946639801718824'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/250946639801718824'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2011/03/best-practice-to-make-linuxandroid.html' title='Best Practice to Make Linux/Android Filesystem Robust'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6448756203283676481.post-4241422858951873228</id><published>2010-05-17T18:51:00.007+08:00</published><updated>2010-05-17T21:25:18.859+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='redmine'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='10.04 trac'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Ubuntu - Install Redmine + MySQL in Ubuntu 10.04</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Introduciton&lt;br /&gt;&lt;br /&gt;Redmine&lt;/span&gt; is an open source,  web-based project management and bug-tracking tool. It includes calendar   and gantt charts to aid visual representation of projects and their  deadlines. It supports multiple projects. Redmine is free and open  source software which provides integrated project management features,  issue tracking, and support for multiple version control options.&lt;br /&gt;&lt;br /&gt;The  design of Redmine is significantly influenced by Trac, a software  package with some similar features.&lt;br /&gt;&lt;br /&gt;Redmine is written using the  Ruby on Rails framework. It is cross-platform and cross-database.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Installation Steps&lt;/span&gt;&lt;br /&gt;The  following are my steps to install it on the new Ubuntu 10.04 system:&lt;br /&gt;1)  install mysql server &amp;amp; phpmyadmin tool&lt;br /&gt;  &lt;blockquote&gt;$ sudo  apt-get  install mysql-server phpmyadmin&lt;/blockquote&gt;You can just set all initial  passwords to &lt;span style="font-style: italic;"&gt; 'admin&lt;/span&gt;'. When finished, you can use &lt;a href="http://localhost/phpmyadmin"&gt;http://localhost/phpmyadmin&lt;/a&gt; to manage your databases.&lt;br /&gt;2) change mysql database directory (optional, I just want to store it in the /srv directory)&lt;br /&gt;  &lt;blockquote&gt;$  mysqladmin -u root  -p shutdown&lt;br /&gt;  $ sudo mv /var/lib/mysql /srv/&lt;br /&gt;   $ sudo vi  /etc/mysql/my.cnf (change datadir value from "/var/lib/mysql" to  "/srv/mysql")&lt;br /&gt;  $  sudo vi /etc/apparmor.d/usr.sbin.mysqld  (replace all "/var/lib/mysql" to "/srv/mysql")&lt;br /&gt;  $ sudo /etc/init.d/mysql  restart (FIXME: doesn't work, I just reboot the system instead)&lt;/blockquote&gt;3) install redmine &amp;amp;  redmine-mysql&lt;br /&gt; &lt;blockquote&gt;$ sudo apt-get install  redmine redmine-mysql&lt;/blockquote&gt;4) install rails...&lt;br /&gt; &lt;blockquote&gt;$ sudo apt-get  install mongrel ruby1.8-dev&lt;br /&gt;&lt;/blockquote&gt;5) change redmine files default directory (optional, I prefer to store them in the /srv directory)&lt;br /&gt;  &lt;blockquote&gt;$ sudo mv /var/lib/redmine /srv/&lt;br /&gt;  $ sudo vi  /usr/share/redmine/config/environment.rb (replace all "/var/lib" to "/srv")&lt;/blockquote&gt;6) test redmine&lt;br /&gt; &lt;blockquote&gt;$ cd /usr/share/redmine&lt;br /&gt;  $ sudo mkdir  /usr/share/redmine/log&lt;br /&gt; $ sudo ruby   /usr/share/redmine/scripts/server -e production&lt;/blockquote&gt;(now in PC   web-browser, you can use &lt;a href="http://localhost:3000"&gt;http://localhost:3000&lt;/a&gt; to do the test)&lt;br /&gt;7) configure apache to run redmine&lt;br /&gt; &lt;blockquote&gt;$ sudo apt-get  install  libapache2-mod-passenger (seems it has been already installed)&lt;br /&gt;  $  sudo ln -s /usr/share/redmine/public /var/www/redmine&lt;br /&gt; $  sudo  a2enmod passanger (seems already been enabled too)&lt;br /&gt; $ sudo  vi  /etc/apache2/site-available/default&lt;br /&gt;  + RailsEnv production&lt;br /&gt;    + RailsBaseURI /redmine&lt;br /&gt; $ sudo chown www-data   /usr/share/redmine/config/environment.rb&lt;br /&gt; $ sudo   /etc/init.d/apache2 reload&lt;/blockquote&gt;That's all. In your PC, you can use:   &lt;a href="http://localhost/redmine"&gt;http://localhost&lt;/a&gt;&lt;ipaddress&gt;&lt;a href="http://localhost/redmine"&gt;/redmine&lt;/a&gt; to access Redmine now.&lt;br /&gt;&lt;/ipaddress&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-4241422858951873228?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/4241422858951873228/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=4241422858951873228' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/4241422858951873228'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/4241422858951873228'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2010/05/ubuntu-install-redmine-mysql-in-ubuntu.html' title='Ubuntu - Install Redmine + MySQL in Ubuntu 10.04'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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-6448756203283676481.post-8171253556790082920</id><published>2008-04-22T19:46:00.001+08:00</published><updated>2008-04-22T20:01:32.577+08:00</updated><title type='text'>Ubuntu - Install privoxy to visit blocked web</title><content type='html'>Privoxy is worked with Tor. And it can forward http requests to socks requests used by Tor.&lt;br /&gt;&lt;br /&gt;1) To install privoxy:&lt;br /&gt;&lt;blockquote&gt;sudo apt-get install privoxy&lt;/blockquote&gt;2) To config privoxy&lt;br /&gt;&lt;blockquote&gt;sudo vi /etc/privoxy/config&lt;/blockquote&gt;listen-address    :8118&lt;br /&gt;forward-socks4a    /    localhost:9050    .&lt;br /&gt;3) To restart privoxy&lt;br /&gt;&lt;blockquote&gt;sudo /etc/init.d/privoxy restart&lt;/blockquote&gt;4) To configure Firefox&lt;br /&gt;Edit-&gt;Preferences-&gt;Advanced-&gt;Network-&gt;Settings-&gt;Manual proxy Configuration:&lt;br /&gt;http prosy: localhost Port: 8118&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-8171253556790082920?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/8171253556790082920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=8171253556790082920' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/8171253556790082920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/8171253556790082920'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2008/04/ubuntu-install-privoxy-to-visit-blocked.html' title='Ubuntu - Install privoxy to visit blocked web'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6448756203283676481.post-3816728398715479077</id><published>2008-01-21T20:38:00.000+08:00</published><updated>2008-01-21T21:30:16.433+08:00</updated><title type='text'>Ubuntu - Install Tor to use the blocked MSN</title><content type='html'>&lt;span style="font-family:trebuchet ms;"&gt;The following step shows how to setup Tor to use the blocked MSN:&lt;br /&gt;1) Install Tor&lt;br /&gt;&lt;blockquote&gt;sudo apt-get install tor&lt;br /&gt;sudo /etc/init.d/tor start&lt;br /&gt;&lt;/blockquote&gt;2) Config MSN for localhost&lt;br /&gt;If your MSN and Tor are running at the same computer, the configuration is, Pidgin for example: Accounts --&gt; Add/Edit --&gt; (account) --&gt; Modify Account --&gt; Advanced --&gt; Proxy Type --&gt; Socks 5 --&gt; Host: localhost, Port: 9050&lt;br /&gt;3) Config for LAN&lt;br /&gt;Open the config file:&lt;br /&gt;&lt;blockquote&gt;sudo vi /etc/tor/torrc&lt;/blockquote&gt;&lt;/span&gt;Find the following line:&lt;br /&gt;&lt;blockquote&gt;SocksListenAddress 127.0.0.1 # accept connections only from localhost&lt;/blockquote&gt;Add a new line:&lt;br /&gt;&lt;blockquote&gt;SocksListenAddress XXX.XXX.XXX.XXX:PORT # accept connections from local network&lt;/blockquote&gt;XXX.XXX.XXX.XXX is the IP address of the pc running Tor, Port is any number not used.&lt;br /&gt;For example:&lt;br /&gt;&lt;blockquote&gt;172.21.18.247:9100&lt;/blockquote&gt;And then restart Tor:&lt;br /&gt;&lt;blockquote&gt;sudo /etc/init.d/tor restart&lt;/blockquote&gt;Pidgin settings: ... --&gt; Host: 172.21.18.247, Port: 9100&lt;br /&gt;That's all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-3816728398715479077?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/3816728398715479077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=3816728398715479077' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/3816728398715479077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/3816728398715479077'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2008/01/ubuntu-install-tor-to-use-blocked-msn.html' title='Ubuntu - Install Tor to use the blocked MSN'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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-6448756203283676481.post-1612105496744331039</id><published>2007-12-19T13:26:00.000+08:00</published><updated>2007-12-19T13:43:30.468+08:00</updated><title type='text'>Ubuntu - Play RM format movies</title><content type='html'>When I tried to play the rmvb format movies the first, the totem player said that the "Realvideo 4.0 decode can not be found", so there was only audio but no video. After I searched the internet about that, I found this site: medibuntu.org which has what I need.&lt;br /&gt;The following shows the step to make my Ubuntu 7.10 pc play the rm movie:&lt;br /&gt;1) Install the mplayer (Add/Remove --&gt; Sound &amp;amp; Video --&gt; check the MPlayer Movie Player)&lt;br /&gt;2) Install w32codecs &amp;amp; libdvdcss2&lt;br /&gt;&lt;blockquote&gt;   a) sudo wget http://www.medibuntu.org/sources.list.d/gutsy.list -O /etc/apt/sources.list.d/medibuntu.list&lt;br /&gt;   b) wget -q http://packages.medibuntu.org/medibuntu-key.gpg -O- | sudo apt-key add - &amp;amp;&amp;amp; sudo apt-get update&lt;br /&gt;   c) sudo apt-get install w32codecs libdvdcss2&lt;br /&gt;&lt;/blockquote&gt;3) Now you can remove the default totem movie player if you like:&lt;br /&gt;   Open the Synaptic Package Manager, uncheck the totem-gstreamer (totem, totem-mozilla) and press Apply button&lt;br /&gt;That's all!&lt;br /&gt;&lt;strong&gt; &lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-1612105496744331039?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/1612105496744331039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=1612105496744331039' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/1612105496744331039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/1612105496744331039'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2007/12/ubuntu-710-play-rm-format-movies.html' title='Ubuntu - Play RM format movies'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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-6448756203283676481.post-6664735274749230424</id><published>2007-11-08T04:00:00.000+08:00</published><updated>2007-11-08T04:19:54.268+08:00</updated><title type='text'>Indent - Beautify your C source code</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Introduction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;GNU Indent is a GNU tool used to make code easier to read. It can also convert from one style of writing C to another.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Default Parameters file&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;indent will use the ~/.indent.pro file as the default parameter file. My content of the .indent.pro is:&lt;br /&gt;&lt;blockquote&gt;-bad -bap -bbb -bbo -nbc -br -bli0 -bls -c33 -cd33 -ncdb -ncdw -ce -cli0 -cp33 -cs -d0 -nbfda -di2 -nfc1 -nfca -hnl -ip5 -l75 -lp -npcs -nprs -npsl -saf -sai -saw -nsc -nsob -nss -i4 -ts4 -ut&lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;Reference:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://linux.die.net/man/1/indent"&gt;http://linux.die.net/man/1/indent&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-6664735274749230424?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/6664735274749230424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=6664735274749230424' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/6664735274749230424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/6664735274749230424'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2007/11/indent-beautify-your-c-source-code.html' title='Indent - Beautify your C source code'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6448756203283676481.post-1833312398380478664</id><published>2007-11-05T02:33:00.000+08:00</published><updated>2007-11-08T04:25:37.435+08:00</updated><title type='text'>ARM GCC inline assembly</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Introduction&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Just now I want to print the ARM CP15 registers' value in a C function, I know I need the inline assembly technology. After read some codes in linux kernel and searched the internet, I have got some simple idea.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Examples&lt;/span&gt;&lt;br /&gt;Read ARM ID code:&lt;br /&gt;&lt;blockquote&gt;u32 val;&lt;br /&gt;__asm__ __volatile__ ("mrc p15, 0, %0, c0, c0, 0" : "=r" (val));&lt;br /&gt;printk("ARM ID code: 0x%x\n", val);&lt;br /&gt;&lt;/blockquote&gt;Write TTB:&lt;br /&gt;&lt;blockquote&gt;u32 val&lt;br /&gt;/*... */&lt;br /&gt;__asm__ __volatile__ ("mcr p15, 0, %0, c2, c0, 0" : : "r" (val));&lt;br /&gt;&lt;/blockquote&gt;For more information, see:&lt;br /&gt;&lt;a href="http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html"&gt;http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-1833312398380478664?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/1833312398380478664/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=1833312398380478664' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/1833312398380478664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/1833312398380478664'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2007/11/arm-gcc-inline-assembly.html' title='ARM GCC inline assembly'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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-6448756203283676481.post-3438819348496680321</id><published>2007-11-05T00:39:00.000+08:00</published><updated>2007-11-08T04:26:52.708+08:00</updated><title type='text'>ARM coprocessor CP15 Summary</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Introduction&lt;/span&gt;&lt;br /&gt;* CP15 is a coprocessor of ARM chip, it used to configure and control the ARM core modules - The caches, Tightly-Coupled Memories (TCMs), Memory Management Unit (MMU), and most other system options.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Instructions&lt;/span&gt;&lt;br /&gt;* You can only access CP15 registers with MRC and MCR instructions in a privileged mode.&lt;br /&gt;&lt;blockquote&gt;mcr{cond} p15, &amp;lt;Opcode_1&amp;gt;, &amp;lt;Rd&amp;gt;, &amp;lt;CRn&amp;gt;, &amp;lt;CRm&amp;gt;, &amp;lt;Opcode_2&amp;gt;&lt;br /&gt;mrc{cond} p15, &amp;lt;Opcode_1&amp;gt;, &amp;lt;Rd&amp;gt;, &amp;lt;CRn&amp;gt;, &amp;lt;CRm&amp;gt;, &amp;lt;Opcode_2&amp;gt;&lt;/blockquote&gt;- The Opcode_1 and Opcode_2 field Should Be Zero except when the values specified are used to select the desired operations.&lt;br /&gt;- The CRm field should be c0 except when the the register specified are used to select the desired behavior.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Registers&lt;/span&gt;&lt;br /&gt;* c0~c15&lt;br /&gt;- c0: used to read ID code/Cache type/TCM status&lt;br /&gt;&amp;gt; read ID code:&lt;br /&gt;&lt;blockquote&gt;mrc p15, 0, &amp;lt;Rd&amp;gt;, c0, c0, 0&lt;br /&gt;&lt;/blockquote&gt;&amp;gt; read Cache type:&lt;blockquote&gt;mrc p15, 0, &amp;lt;Rd&amp;gt;, c0, c0, 1&lt;br /&gt;&lt;/blockquote&gt;&amp;gt; read TCM status:&lt;br /&gt;&lt;blockquote&gt;mrc p15, 0, &amp;lt;Rd&amp;gt;, c0, c0, 2&lt;br /&gt;&lt;/blockquote&gt;- c1: used to enable/disable caches and MMU&lt;br /&gt;&amp;gt; read control register:&lt;br /&gt;&lt;blockquote&gt;mrc p15, 0, &amp;lt;Rd&amp;gt;, c1, c0, 0&lt;br /&gt;&lt;/blockquote&gt;&amp;gt; write control register:&lt;br /&gt;&lt;blockquote&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c1, c0, 0&lt;br /&gt;&lt;/blockquote&gt;- c2: r/w Translation Table Base (TTB)&lt;br /&gt;&lt;blockquote&gt;mrc p15, 0, &amp;lt;Rd&amp;gt;, c2, c0, 0; read TTBR&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c2, c0, 0; write TTBR&lt;br /&gt;&lt;/blockquote&gt;- c3: Domain access control&lt;br /&gt;&lt;blockquote&gt;mrc p15, 0, &amp;lt;Rd&amp;gt;, c3, c0, 0; read domain access permissions&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c3, c0, 0; write domain access permissions&lt;br /&gt;&lt;/blockquote&gt;- c4: Reserved in ARM926EJ-S&lt;br /&gt;- c5: Data fault status/Instruction fault status&lt;br /&gt;- c6: Fault address&lt;br /&gt;- c7: Cache operations&lt;br /&gt;&lt;blockquote&gt;mrc p15, 0, &amp;lt;Rd&amp;gt;, c7, c7, 0; Invalidate ICache and DCache&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c7, c5, 0; Invalidate ICache&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c7, c5, 1; Invalidate ICache single entry (MVA)&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c7, c5, 2; Invalidate ICache single entry (Set/Way)&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c7, c13, 1; Prefetch ICache line (MVA)&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c7, c6, 0; Invalidate DCache&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c7, c6, 1; Invalidate DCache single entry (MVA)&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c7, c6, 2; Invalidate DCache single entry (Set/Way)&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c7, c10, 1; Clean DCache single entry (MVA)&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c7, c10, 2; Clean DCache single entry (Set/Way)&lt;br /&gt;mrc p15, 0, &amp;lt;Rd&amp;gt;, c7, c10, 3; Test and clean DCache&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c7, c14, 1; Clean and invalidate DCache entry (MVA)&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c7, c14, 2; Clean and invaliate DCache entry (Set/Way)&lt;br /&gt;mrc p15, 0, &amp;lt;Rd&amp;gt;, c7, c14, 3; Test, clean, and invalidate DCache&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c7, c10, 4; Drain write buffer&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c7, c0, 4; Wait for interrupt&lt;br /&gt;&lt;/blockquote&gt;&amp;gt; Clean the entire DCache:&lt;br /&gt;&lt;blockquote&gt;tc_loop:&lt;br /&gt;mrc p15, 0, r15, c7, c10, 3; test and clean, pc is not changed by this instrunction&lt;br /&gt;bne tc_loop&lt;br /&gt;&lt;/blockquote&gt;&amp;gt; Clean and invalidate the entire DCache:&lt;br /&gt;&lt;blockquote&gt;tci_loop:&lt;br /&gt;mrc p15, 0, r15, c7, c14, 3; test clean and invalidate&lt;br /&gt;bne tci_loop&lt;br /&gt;&lt;/blockquote&gt;- c8: (W) TLB operations&lt;br /&gt;- c9: Cache lockdown/TCM region&lt;br /&gt;&lt;blockquote&gt;mrc p15, 0, &amp;lt;Rd&amp;gt;, c9, c0, 0; read DCache lockdown register&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c9, c0, 0; write DCache lockdown register&lt;br /&gt;mrc p15, 0, &amp;lt;Rd&amp;gt;, c9, c0, 1; read ICache lockdown register&lt;br /&gt;mcr p15, 0, &amp;lt;Rd&amp;gt;, c9, c0, 1; write ICache lockdown register&lt;br /&gt;&lt;/blockquote&gt;- c10: TLB lockdown&lt;br /&gt;- c11/c12: Reserved in ARM926EJ-S&lt;br /&gt;- c13: FCSE PID/Context ID&lt;br /&gt;- c14: Reserved in ARM926EJ-S&lt;br /&gt;- c15: Test configuration&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-3438819348496680321?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/3438819348496680321/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=3438819348496680321' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/3438819348496680321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/3438819348496680321'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2007/11/arm-coprocessor-cp15-summary.html' title='ARM coprocessor CP15 Summary'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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-6448756203283676481.post-86333974031758446</id><published>2007-10-22T21:26:00.000+08:00</published><updated>2007-12-19T15:30:33.486+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu Linux svn subversion apache trac'/><title type='text'>Ubuntu - Install subversion over apache2 &amp; trac</title><content type='html'>&lt;span style="font-family:trebuchet ms;"&gt;This article covers installation &lt;span style="color: rgb(51, 204, 0);"&gt;&lt;strong&gt;subversion&lt;/strong&gt;&lt;/span&gt; over &lt;span style="color: rgb(51, 204, 0);"&gt;&lt;strong&gt;apache2&lt;/strong&gt;&lt;/span&gt; and &lt;strong&gt;&lt;span style="color: rgb(51, 204, 0);"&gt;trac&lt;/span&gt;&lt;/strong&gt; so that it can be easily accessed from other systems on a public network. Multiple projects are supported in this installation.&lt;br /&gt;&lt;br /&gt;1. install related packages&lt;br /&gt;You can use the &lt;em&gt;Synaptic Package Manager&lt;/em&gt; or the &lt;em&gt;sudo apt-get install&lt;/em&gt; command to download and install packages. The following steps only show the &lt;em&gt;sudo apt-get install&lt;/em&gt; method.&lt;br /&gt;1) install subversion&lt;br /&gt;&lt;/span&gt;&lt;div style="text-align: left;"&gt;&lt;blockquote&gt;sudo apt-get install subversion&lt;/blockquote&gt;&lt;/div&gt;&lt;span style="font-family:trebuchet ms;"&gt;2) install apache2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;Install apache2 (+apache2-mpm-worker, apache2-utils, apache2.2-common, apache2-doc &amp;amp; libapache2-svn)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;blockquote&gt;&lt;span style="font-family:trebuchet ms;"&gt;sudo apt-get install apache2 libapache2-svn&lt;/span&gt;&lt;/blockquote&gt;3) install trac&lt;br /&gt;Install trac (+python-clearsilver, python-pysqlite2, python-subversion, libapache2-mod-python &amp;amp; libapache2-mod-python-doc)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;blockquote&gt;&lt;span style="font-family:trebuchet ms;"&gt;sudo apt-get install trac libapache2-mod-python libapache2-mod-python-doc&lt;/span&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;"&gt;2. create svn repository&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;There are several typical places to put a subversion repository; most common places are: /srv/svn, /usr/local/svn &amp;amp; /home/svn. The following comand uses the /srv/svn:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;blockquote&gt;&lt;span style="font-family:trebuchet ms;"&gt;sudo mkdir -p /srv/svn&lt;/span&gt;&lt;/blockquote&gt;The /srv/svn is a root directory for multiple projects. To create a project use the command like this:&lt;br /&gt;&lt;blockquote&gt;sudo svnadmin create /srv/svn/project1&lt;/blockquote&gt;The &lt;span style="font-style: italic;"&gt;project1&lt;/span&gt; is the project name, you can change to your project name. And then change the owner of the folder:&lt;br /&gt;&lt;blockquote&gt;sudo chown -R www-data:www-data /srv/svn/project&lt;/blockquote&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;"&gt;Modify the configuration file: &lt;blockquote&gt;sudo vi /etc/apache2/mods-available/dav_svn.conf&lt;/blockquote&gt;&lt;blockquote&gt;    &amp;lt;Location /svn&amp;gt;&lt;br /&gt;    DAV svn&lt;br /&gt;    SVNParentPath   /srv/svn&lt;br /&gt;    AuthType Basic&lt;br /&gt;    AuthName "Subversion Repository"&lt;br /&gt;    AuthUserFile /etc/apache2/dav_svn.passwd&lt;br /&gt;    &amp;amp;LimitExcept ...&amp;gt; &amp;lt;/LimitExcept&amp;gt;&lt;br /&gt;&amp;lt;/Location&amp;gt;&lt;/blockquote&gt;After the changes have been made, restart the apache2: &lt;blockquote&gt;sudo /etc/init.d/apache2 restart&lt;/blockquote&gt;Create user account and set password (please change bhduan to your own user account):&lt;br /&gt;&lt;blockquote&gt;sudo htpasswd -cm /etc/apache2/dav_svn.passwd bhduan&lt;/blockquote&gt;3. Create trac Environments Directory&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Trebuchet MS;"&gt;&lt;blockquote&gt;&lt;span style="font-family:Trebuchet MS;"&gt;sudo mkdir /srv/trac&lt;/span&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;span style="font-family:Trebuchet MS;"&gt;This is the root directory for multiple projects. If you put your environment somewhere else, make sure to note that and use that location in the appropriate places in the next steps. To enable the trac site by the apache2 server:&lt;br /&gt;&lt;blockquote&gt;cd /etc/apache2/sites-available&lt;br /&gt;sudo cp default trac&lt;br /&gt;sudo vi trac&lt;br /&gt;&amp;lt;Location&amp;gt;&lt;br /&gt;    SetHandler mod_python&lt;br /&gt;    PythonHandler trac.web.modpython_frontend&lt;br /&gt;    PythonOption TracEnvParentDir /srv/trac&lt;br /&gt;    PythonOption TracUrlRoot /trac&lt;br /&gt;&amp;lt;/Location&amp;gt;&lt;br /&gt;sudo a2dissite default&lt;br /&gt;sudo a2ensite trac&lt;br /&gt;sudo /etc/init.d/apache2 reload&lt;/blockquote&gt;To create and initialize the trac environment:&lt;br /&gt;&lt;blockquote&gt;sudo trac-admin /srv/trac/project1 initenv&lt;/blockquote&gt;Please note that you must fill the correct svn path (/srv/svn), change the owner:&lt;br /&gt;&lt;blockquote&gt;sudo chown -R www-data:www-data /srv/trac&lt;/blockquote&gt;Set authenfication:&lt;br /&gt;&lt;blockquote&gt;sudo vi /etc/apache2/sites-available/trac&lt;/blockquote&gt;Add the following lines before &amp;lt;/Location&amp;gt;&lt;br /&gt;&lt;blockquote&gt;    &amp;lt;Location /trac&amp;gt;&lt;br /&gt;      # ...&lt;br /&gt;       AuthType    Basic&lt;br /&gt;       AuthName    "Trac Projects"&lt;br /&gt;       AuthUserFile /etc/apache2/dav_svn.passwd&lt;br /&gt;       Require valid-user&lt;br /&gt;&amp;lt;/Location&amp;gt;&lt;/blockquote&gt;4. Create new project example&lt;br /&gt;The following example shows the steps to create a project named as &lt;span style="font-style: italic;"&gt;linux:&lt;/span&gt;&lt;br /&gt;1) Open a Terminal and change the current directory to /srv/svn&lt;br /&gt;&lt;blockquote&gt;cd /srv/svn&lt;/blockquote&gt;2) Create a new project named as linux&lt;br /&gt;&lt;blockquote&gt;sudo svnadmin create linux&lt;/blockquote&gt;3) Change the owner of the folder and its sub directories and files:&lt;br /&gt;&lt;blockquote&gt;sudo chown -R www-data:www-data linux&lt;/blockquote&gt;4) Change current directory to trac&lt;br /&gt;&lt;blockquote&gt;cd /srv/trac&lt;/blockquote&gt;5) Create and initialize the linux trac environment, set &lt;span style="font-style: italic;"&gt;Project Name [My Project] &amp;gt;&lt;/span&gt; as &lt;span style="font-style: italic;"&gt;Linux&lt;/span&gt; and set  &lt;span style="font-style: italic;"&gt;Path to repository [/path/to/repos]&amp;gt; &lt;/span&gt;to &lt;span style="font-style: italic;"&gt;/srv/svn/linux&lt;/span&gt;, and use default value for other options:&lt;br /&gt;&lt;blockquote&gt;sudo trac-admin /srv/trac/linux initenv&lt;/blockquote&gt;6) Also change its owner&lt;br /&gt;&lt;blockquote&gt;sudo chown -R www-data:www-data linux&lt;/blockquote&gt;7) Change current directory to your project's working folder, the following just shows the empty project in a tmp foler:&lt;br /&gt;&lt;blockquote&gt;mkdir ~/tmp&lt;br /&gt;cd ~/tmp&lt;br /&gt;mkdir branches tags trunk&lt;/blockquote&gt;8) Import the project to the svn&lt;br /&gt;&lt;blockquote&gt;svn import -m "original version for testing" ./ http://localhost/svn/linux&lt;/blockquote&gt;Here I use the localhost as the svn server address, you can change it to your real svn server ip address.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-86333974031758446?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/86333974031758446/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=86333974031758446' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/86333974031758446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/86333974031758446'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2007/10/ubuntu-install-subversion-over-apache2.html' title='Ubuntu - Install subversion over apache2 &amp; trac'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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-6448756203283676481.post-5087657552970708002</id><published>2007-10-22T16:43:00.000+08:00</published><updated>2007-10-23T12:43:43.170+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu Samba Linux'/><title type='text'>Ubuntu - Setup Samba</title><content type='html'>&lt;span style="font-family:trebuchet ms;"&gt;If you want to share files between your Ubuntu and Windows computers, your best option is to use Samba file sharing. The following steps describe howto setup Samba:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;1. Install Samba&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;If Samba is not installed in your system, you must first install it. You can use the Synaptic Package Manager or the following command:&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:trebuchet ms;"&gt;sudo apt-get install samba&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-family:trebuchet ms;"&gt;2. Configure smb&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;We've got samba installed, but now we'll need to configure it to make it accessible. Run following command to open the configuration file, substituting your editor of choice:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;blockquote&gt;&lt;span style="font-family:trebuchet ms;"&gt;sudo vim /etc/samba/smb.conf&lt;/span&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;"&gt;Uncomment some lines to make the following valid:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;blockquote&gt;&lt;span style="font-family:trebuchet ms;"&gt;[homes]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;security = user&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;comment = Home Directories&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;browseable = no&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;valid users = %S&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;writable = yes&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;create mask = 0600&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;directory mask = 0700&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;"&gt;3. Create a Samba User&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;blockquote&gt;&lt;span style="font-family:trebuchet ms;"&gt;sudo smbpasswd -a [username]&lt;username&gt;&lt;username&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;"&gt;4. Restart Samba&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;blockquote&gt;&lt;span style="font-family:trebuchet ms;"&gt;sudo /etc/init.d/samba restart&lt;/span&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;"&gt;Now your home directory is shared, I tried this in the Ubuntu 7.04 &amp;amp; 7.10.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-5087657552970708002?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/5087657552970708002/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=5087657552970708002' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/5087657552970708002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/5087657552970708002'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2007/10/ubuntu-setup-samba.html' title='Ubuntu - Setup Samba'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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-6448756203283676481.post-5071082223352639847</id><published>2006-11-23T20:36:00.000+08:00</published><updated>2007-11-08T04:28:18.227+08:00</updated><title type='text'>WinCE - Share a data segment in a DLL</title><content type='html'>&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;A DLL can be loaded by more than one process. For every process the DLL's code segment is shared but each process gets its own data segment by default. Therefore if one process changes the value of the DLL's global variable, the other process can not get the modified value. For sharing some global variables of the DLL among several processes, we can use the shared data segment.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Example Code&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;// Global and static member variables that are not shared defined here.&lt;/span&gt;&lt;br /&gt;...&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;// Begin the shared data segment&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 102, 255);"&gt;#pragma data_seg&lt;/span&gt;("SHARED")&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;// Define simple variables, the variable must be initialized here, otherwise it will not be shared.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;int&lt;/span&gt; gSharedTest = &lt;span style="color: rgb(204, 0, 0);"&gt;0&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;// Do not define classes that require 'deep' copy constructors.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 102, 255);"&gt;#pragma data_seg&lt;/span&gt;()&lt;br /&gt;&lt;span style="color: rgb(51, 204, 0);"&gt;// End the shared data segment and default back to the normal data segment behavior.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 204, 0);"&gt;// Tells the linker to generate the shared data segment.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;#pragma comment&lt;/span&gt;(linker, "/section:SHARED,RWS")&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Remarks&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;1) The upper "SHARED" is the name of the segment, you can use another name. It should be appeared both in the data_seg and comment part.&lt;br /&gt;2) The address of the shared variable must lie in this data segment, so variables allocated from heap can not be shared.&lt;br /&gt;3) The variable must be initialized otherwise it won't be shared.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-5071082223352639847?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/5071082223352639847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=5071082223352639847' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/5071082223352639847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/5071082223352639847'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2006/11/about-share-data-segment-in-dll.html' title='WinCE - Share a data segment in a DLL'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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-6448756203283676481.post-2001441164571918640</id><published>2006-11-22T15:45:00.000+08:00</published><updated>2007-11-08T04:31:09.652+08:00</updated><title type='text'>WinCE - Using Protected Server Libraries (PSL)</title><content type='html'>&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;As we know, Windows CE threads can migrate between processes while executing API calls, it borrows the caller's thread and places it in the server process. Such servers are called "Protected Server Libraries" (PSLs) and are processes that export services like DLLs.&lt;br /&gt;&lt;br /&gt;Protected Server Libraries (PSL) are used by Windows CE to create API sets that in their own process address space and can server multiple clients concurrently. Windows CE implements all of its system APIs using this technique including all WIN32 APIs, User interface, device driver, and many of its DirectX interfaces. There is a one to one mapping between an API call and its corresponding PSL entry.&lt;br /&gt;&lt;br /&gt;Windows CE implements PSL support through a clever technique generating special processor fault conditions that cause the execution of PSL entry points. The system maintains a table of &lt;span style="color: rgb(51, 204, 0);"&gt;&lt;strong&gt;32&lt;/strong&gt;&lt;/span&gt; PSL entries. All entries between &lt;strong&gt;&lt;span style="color: rgb(51, 204, 0);"&gt;0&lt;/span&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;span style="color: rgb(51, 204, 0);"&gt;24&lt;/span&gt;&lt;/strong&gt; are preassigned and may not be used for custom PSLs. PSLs register their APIs, associating their API with one particular entry in the PSL table. Part of the PSL registration process is providing the system with a function table of all the API entry points for a particular PSL. There are also a set of macros defined in &lt;em&gt;psyscall.h&lt;/em&gt; which take the PSL id and an index into the registered function table to indicate which particular function for the specified PSL is to be called. This macro generates a 'function pointer' that really is an &lt;span style="color: rgb(204, 0, 0);"&gt;invalid&lt;/span&gt; memory address. When this function pointer gets used it causes the processor to fault. The fault handling code then inspects the faulty address and sees that it is one of the special PSL addresses and extracts the PSL id and function table index. It then turns around and calls the correct entry point in the PSL, just as if the caller had directly jumped to it – with one significant difference in that process address spaces have been jumped across as well. When the PSL function finishes execution and returns, the OS resumes the application that called the PSL to begin with by returning from the fault condition with the return value from the PSL function. The application resumes execution and it looks just as if a function call had occurred. Because PSLs are the core way APIs are implemented in the system the code path for executing this process is very streamlined.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Components of PSL&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;PSLs have four main components:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Functions implementing the various entry points of the PSL.&lt;/li&gt;&lt;li&gt;Function table (a Vtable) that is an array of function pointers containing all the entry points of the PSL. This is an array of pointers to the functions making up the API set (PSL entries). The first two entries are reserved for the kernel. The first entry is the notification procedure that the kernel will call any time a thread or a process is stopped or started, low memory occurs, or the system is booted. The second entry is reserved by the kernel and should be zero. All remaining entries are available to the PSL implementer.&lt;/li&gt;&lt;li&gt;Signature table describing all the argument types for each function in the function table. Made up of an array of 2 or more entry points with a one to one correspondence to the API function table. You can use these macros: &lt;em&gt;&lt;span style="color: rgb(102, 0, 0);"&gt;FNSIG0-12&lt;/span&gt;, &lt;span style="color: rgb(102, 0, 0);"&gt;DW&lt;/span&gt;&lt;/em&gt; - DWORD, &lt;em&gt;&lt;span style="color: rgb(102, 0, 0);"&gt;PTR&lt;/span&gt;&lt;/em&gt; - Pointer, &lt;em&gt;&lt;span style="color: rgb(102, 0, 0);"&gt;I64&lt;/span&gt;&lt;/em&gt; - 64 bit integer. PSL functions can have one of three argument types (DW, PTR, I64) or no arguments at. Those types are a DWORD (unsigned long), a pointer (void *), or a 64 bit integer (long long). There return values are the same. They can be used in any combination within a function or across function. There can be no other parameter types but the current parameter types can be used to contain other types (like a WORD or WCHAR in a DWORD, a BSTR in a void *). PSL functions can have from zero to 12 arguments. As can be seen above, each PSL function signiture is defined by using an FNSIG macro that is followed by the number of arguments the function has. The FNSIG macro is then filled in with an argument type specification for each argument it has.&lt;br /&gt;The data in the signature table is used by the kernel to marshal arguments for the PSL function calls across process address spaces so it is imperative that these be correct or arguments will not get passed correctly from a client calling your PSL into the actual function in your PSL that implements the API call.&lt;/li&gt;&lt;li&gt;A .lib that clients of the PSL link to which contains the code that generates the special invalid memory address that causes the processor to fault and execute the PSL. The code also can be inline functions defined in the header file.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The following is the code fragment of using the PSL technique to add APIs to our customizing Power Manager. The example shows the steps to add the SetSystemPowerRequirement API.&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;// 1. Functions &lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;// 1.1 Notify function&lt;br /&gt;&lt;/span&gt;&lt;code&gt;VOID&lt;br /&gt;PmAPINotifyProc(DWORD dwEvent, DWORD dwProcessId, DWORD dwThreadId)&lt;br /&gt;{&lt;br /&gt;switch (dwEvent)&lt;br /&gt;{&lt;br /&gt;case DLL_PROCESS_ATTACH:&lt;br /&gt;PMLOGMSG(ZONE_INIT,(TEXT("DLL_PROCESS_ATTACH ProcessId %X, ThreadId %X\r\n"), dwProcessId, dwThreadId));&lt;br /&gt;break;&lt;br /&gt;case DLL_THREAD_ATTACH:&lt;br /&gt;PMLOGMSG(ZONE_INIT,(TEXT("DLL_THREAD_ATTACH ProcessId %X, ThreadId %X\r\n"), dwProcessId, dwThreadId));&lt;br /&gt;break;&lt;br /&gt;case DLL_THREAD_DETACH:&lt;br /&gt;PMLOGMSG(ZONE_INIT,(TEXT("DLL_THREAD_DETACH ProcessId %X, ThreadId %X\r\n"), dwProcessId, dwThreadId));&lt;br /&gt;break;&lt;br /&gt;case DLL_PROCESS_DETACH:&lt;br /&gt;PMLOGMSG(ZONE_INIT,(TEXT("DLL_PROCESS_DETACH ProcessId %X, ThreadId %X\r\n"), dwProcessId, dwThreadId));&lt;br /&gt;break;&lt;br /&gt;case DLL_PROCESS_EXITING:&lt;br /&gt;PMLOGMSG(ZONE_INIT,(TEXT("DLL_PROCESS_EXITING ProcessId %X, ThreadId %X\r\n"), dwProcessId, dwThreadId));&lt;br /&gt;break;&lt;br /&gt;case DLL_SYSTEM_STARTED:&lt;br /&gt;PMLOGMSG(ZONE_INIT,(TEXT("DLL_SYSTEM_STARTED ProcessId %X, ThreadId %X\r\n"), dwProcessId, dwThreadId));&lt;br /&gt;break;&lt;br /&gt;default:&lt;br /&gt;break;&lt;br /&gt;}&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;// 1.2 Real API&lt;/span&gt;&lt;br /&gt;&lt;code&gt;EXTERN_C HANDLE WINAPI&lt;br /&gt;PmSetSystemPowerRequirement(LPCTSTR pszName)&lt;br /&gt;{&lt;br /&gt;HANDLE hRequirement = NULL;&lt;br /&gt;//...&lt;br /&gt;return hRequirement;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;// 2. API function table&lt;/span&gt;&lt;br /&gt;&lt;code&gt;static VOID PmAPINotifyProc(DWORD dwEvent, DWORD dwProcessId, DWORD dwThreadId);&lt;br /&gt;const PFNVOID VTable[] = {&lt;br /&gt;(PFNVOID)PmAPINotifyProc,&lt;br /&gt;(PFNVOID)NULL,&lt;br /&gt;(PFNVOID)PmSetSystemPowerRequirement,&lt;br /&gt;};&lt;/code&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;// 3. Signatures table&lt;/span&gt;&lt;br /&gt;&lt;code&gt;#define NUM_APIS (sizeof(VTable) / sizeof(VTable[0]))&lt;br /&gt;const DWORD SigTable[NUM_APIS] = {&lt;br /&gt;FNSIG3(DW, DW, DW), // PmAPINotifyProc&lt;br /&gt;FNSIG0(), // Kernel reserved entry&lt;br /&gt;FNSIG1(PTR), // Signature of PmSetSystemPowerRequirement&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;// 4. Client APIs (defined in header file)&lt;/span&gt;&lt;br /&gt;&lt;code&gt;#define PM_APISET_ID 25 // APISet ID&lt;br /&gt;#define PM_APISET_NAME "CPM" // APISet Name&lt;br /&gt;&lt;br /&gt;#define PmSetSystemPowerRequirement_xxx \&lt;br /&gt;PRIV_IMPLICIT_DECL(HANDLE, PM_APISET_ID, 3, (LPCTSTR psz))&lt;br /&gt;&lt;br /&gt;__inline HANDLE&lt;br /&gt;SetSystemPowerRequirement(LPCTSTR pszState) {&lt;br /&gt;ASSERT(QueryAPISetID(PM_APISET_NAME) == PM_APISET_ID);&lt;br /&gt;return IsAPIReady(PM_APISET_ID) ? PmSetSystemPowerRequirement_xxx(pszState) : NULL;&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;// 5. Create and register APISet&lt;/span&gt;&lt;br /&gt;&lt;code&gt;// PSL Initialization&lt;br /&gt;ghPmAPISet = CreateAPISet(PM_APISET_NAME, NUM_APIS, VTable, SigTable);&lt;br /&gt;if (ghPmAPISet == NULL) {&lt;br /&gt;PMLOGMSG(ZONE_ERROR, (_T("%s: CreateAPISet() failed: %d\r\n"), pszFname, GetLastError()));&lt;br /&gt;return FALSE;&lt;br /&gt;}&lt;br /&gt;if (!RegisterAPISet(ghPmAPISet, PM_APISET_ID)) {&lt;br /&gt;PMLOGMSG(ZONE_ERROR, (_T("%s: RegisterAPISet() failed: %d\r\n"), pszFname, GetLastError()));&lt;br /&gt;CloseHandle(ghPmAPISet);&lt;br /&gt;return FALSE;&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-2001441164571918640?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/2001441164571918640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=2001441164571918640' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/2001441164571918640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/2001441164571918640'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2006/11/using-protected-server-libraries-psl.html' title='WinCE - Using Protected Server Libraries (PSL)'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6448756203283676481.post-6427410110137535356</id><published>2006-09-09T13:43:00.000+08:00</published><updated>2006-12-15T08:01:05.934+08:00</updated><title type='text'>FlashDisk Bad Block Management</title><content type='html'>&lt;div align="justify"&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Bad blocks are blocks that contain one or more invalid bits whose reliability is not guaranteed. Bad blocks may be present when the device is shipped, or may develop during the lifetime of the device.&lt;br /&gt;Devices with bad blocks have the same quality level and the same AC and DC characteristics as devices where all the blocks are valid. A bad block does not affect the performance of valid blocks because it is isolated from the bit line and common source line by a select transistor.&lt;/div&gt;&lt;div align="justify"&gt;As the failure of a page program operation does not affect the data in other pages in the same block, the block can be replaced by re-programming the current data and copying the rest of the replaced block to an available valid block.&lt;/div&gt;&lt;div align="justify"&gt;&lt;/div&gt;&lt;div align="justify"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;p&gt;&lt;div align="justify"&gt;&lt;strong&gt;FlashDisk BBM&lt;/strong&gt;&lt;/div&gt;&lt;div align="justify"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div align="justify"&gt;&lt;/div&gt;&lt;p&gt;&lt;div align="justify"&gt;FlashDisk implements the Bad Block Management in the Flash Translation Layer (FTL), not in the FMD layer. In FlashDisk, some good blocks are reserved for garbage collection and for replacing the runtime bad blocks.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-6427410110137535356?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/6427410110137535356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=6427410110137535356' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/6427410110137535356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/6427410110137535356'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2006/09/flashdisk-bad-block-management.html' title='FlashDisk Bad Block Management'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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-6448756203283676481.post-1385375537990086078</id><published>2006-09-08T23:55:00.000+08:00</published><updated>2006-12-15T08:05:27.117+08:00</updated><title type='text'>FlashDisk Garbage Collection</title><content type='html'>&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;In FlashDisk when the file system write a sector through FlashDisk interface, the data is written to a new free sector position and the old sector with the same logical number is marked as invalid state. After a certain number of sector writes, the free sectors will become low, so a garbage collection is used to free the invalid flash memory space to allow further write operations.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Garbage Collection&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Garbage collection is performed when the number of free sectors in the whole Flash is lower than a specified threshold value. It copies the valid sectors into new (free) sectors and erases the original invalid block.&lt;br /&gt;The basic operations involved in Garbage Collection are the following:&lt;br /&gt;1) The block with invalid sectors are selected for garbage collection. The selection follows an algorithm considered the performance and wear leveling.&lt;br /&gt;2) The valid sectors are copied into a free sector in another block.&lt;br /&gt;3) The block without valid sectors is erased and put to free block list.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Background Thread&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;There is a background thread in the FlashDisk which can be activated to optimize the overall performance. With this thread, the long erase times of Flash devices are completely transparent as the Garbage Collection is activated during the system's idle time. In this way, the FlashDisk erases sectors to free flash memory space automatically, and not only when the number of data sectors to be written exceeds the number of free sectors.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-1385375537990086078?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/1385375537990086078/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=1385375537990086078' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/1385375537990086078'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/1385375537990086078'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2006/09/flashdisk-garbage-collection.html' title='FlashDisk Garbage Collection'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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-6448756203283676481.post-4556520428530851812</id><published>2006-09-08T23:06:00.000+08:00</published><updated>2006-09-08T23:50:41.507+08:00</updated><title type='text'>FlashDisk Wear Leveling Algorithm</title><content type='html'>&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;As we know that in SLC (Single Level Cell) NAND Flash memories each physical block can be programmed or erased reliably over 100,000  to 1,000,000 times on current technology. To increase the lifetime of the NAND Flash, a Wear Leveling Algorithm is implemented in FlashDisk to monitor and spread the number of write cycles per block.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;First-Level Wear Leveling&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;In the first level Wear Leveling new data is programmed to the free blocks that have had the fewest write cycles. In FlashDisk, all the free physical blocks are gathered to a free blocks chain. Each time a virtual block needs to be allocated, a physical block is selected (by the Wear Leveling algorithm) from the chain.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Second-Level Wear Leveling&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;In the 2nd level wear leveling, long-lived data is copied to another block so that the original block can be used for more frequently-changed data.&lt;br /&gt;The 2nd level wear leveling is triggered when the difference between the maximum and the minmum number of write cycles per block reaches a specific threshold. With this particular technique, the mean age of physical NAND blocks is maintained constant.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-4556520428530851812?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/4556520428530851812/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=4556520428530851812' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/4556520428530851812'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/4556520428530851812'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2006/09/flashdisk-wear-leveling-algorithm.html' title='FlashDisk Wear Leveling Algorithm'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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-6448756203283676481.post-1316966224060919576</id><published>2006-09-06T21:59:00.000+08:00</published><updated>2006-09-06T22:00:00.868+08:00</updated><title type='text'>Installable ISR</title><content type='html'>&lt;div align="justify"&gt;&lt;em&gt;&lt;span style="color:#009900;"&gt;Origin of writing this article is that when I am working to support the Microsoft Windows Automotive for ARM platform project, there is a requirement to support the installable isr for LCD interrupt. After I finished it, I summarize the process and write this article.&lt;/span&gt;&lt;/em&gt;&lt;/div&gt;&lt;div align="justify"&gt;&lt;/div&gt;&lt;p&gt;&lt;div align="justify"&gt;&lt;/div&gt;&lt;div align="justify"&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;An installable interrupt service routine (ISR) is one that can be installed and allowed to hook an interrupt after the kernel is built. Usually, if an interrupt had to be hooked to service some event, the code had to be built into the kernel when it was originally built. If a new device was inserted into the board, the code to handle the IRQ would need to already be in the kernel; otherwise, the IRQ could not be hooked.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Interrupt Handling&lt;/strong&gt;&lt;br /&gt;The main technique for handling an interrupt is to associate an event to a specified ISR. Windows CE schedules your IST when the event is triggered.&lt;br /&gt;&lt;br /&gt;1) Typical normal interrupt handling sequence:&lt;br /&gt;a) Hardware raises an interrupt.&lt;br /&gt;b) Kernel looks up IRQ of the interrupt, calls the registered ISR, and disables all lower-priority interrupts.&lt;br /&gt;c) ISR performs necessary handling, and then returns an interrupt identifier (SYSINTR_xxx).&lt;br /&gt;d) If the interrupt identifier value returned by the ISR is &lt;em&gt;SYSINTR_NOP&lt;/em&gt;, kernel completes processing without setting an event. all interrupts enabled. Otherwise, kernel sets the event. When the ISR returns, the kernel enables all other interrupts except the one that is being processed.&lt;br /&gt;e) The kernel schedules the IST indicated by the SYSINTR to run.&lt;br /&gt;f) IST call &lt;em&gt;InterruptDone&lt;/em&gt;, &lt;em&gt;InterruptDone&lt;/em&gt; calls &lt;em&gt;OEMInterruptDone&lt;/em&gt; to perform any hardware actions necessary to enable the next interrupt of the target device.&lt;br /&gt;&lt;br /&gt;2) Function call sequence in the interrupt handling&lt;br /&gt;&lt;em&gt;InterruptInitialize&lt;/em&gt; --&gt; &lt;em&gt;OEMInterruptEnable&lt;/em&gt; --&gt; &lt;em&gt;OALIntrEnableIrqs&lt;/em&gt;&lt;br /&gt;&lt;em&gt;InterruptDisable&lt;/em&gt; --&gt; &lt;em&gt;OEMInterruptDisable&lt;/em&gt; --&gt; &lt;em&gt;OALIntrDisableIrqs&lt;/em&gt;&lt;br /&gt;&lt;em&gt;InterruptDone&lt;/em&gt; --&gt; &lt;em&gt;OEMInterruptDone&lt;/em&gt; --&gt; &lt;em&gt;OALIntrDoneIrqs&lt;/em&gt;&lt;br /&gt;Hardware IRQ --&gt; &lt;em&gt;OEMInterruptHandler&lt;/em&gt; --&gt; static ISRs or installable ISRs --&gt; IST&lt;br /&gt;&lt;br /&gt;For an installable ISR, driver's IST is the same with the normal ISR, both of them will call &lt;em&gt;InterruptInitialize&lt;/em&gt;, &lt;em&gt;WaitForSingleObject&lt;/em&gt;, &lt;em&gt;InterruptDone&lt;/em&gt;, &lt;em&gt;InterruptDisable&lt;/em&gt; functions. Installable ISR will be called by the &lt;em&gt;OEMInterruptHandler&lt;/em&gt;, If &lt;em&gt;OEMInterruptHandler&lt;/em&gt; doesn't &lt;em&gt;NKCallIntChain&lt;/em&gt;, the installable ISR will not be called. Installable ISR does things just like the static ISR does in the &lt;em&gt;OEMInterruptHandler&lt;/em&gt; called functions, so the enable/disable interrupt still need be implemented in the OAL. We can only use the installable ISR for those IRQs that had been handled in the &lt;em&gt;OALIntrEnableIrqs&lt;/em&gt;, &lt;em&gt;OALIntrDisableIrqs&lt;/em&gt; &amp; &lt;em&gt;OALIntrDoneIrqs&lt;/em&gt; function.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Related Functions in Driver&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;1) &lt;strong&gt;LoadIntChainHandler&lt;/strong&gt;&lt;br /&gt;&gt; This function is called by a driver to install an ISR to handle a particular interrupt.&lt;br /&gt;&gt; Parameters: DLL name, ISR function name, IRQ value.&lt;br /&gt;&gt; Return value: the handle to the installed handler, NULL if failed.&lt;br /&gt;&gt; Default ISR for all interrupt is the OEMInterruptHandler&lt;br /&gt;&gt; Sample code:&lt;br /&gt;&lt;span style="color:#330099;"&gt;HANDLE hIISR = LoadIntChainHandler(_T("lcd_isr.dll"), _T("LcdISR"), IRQ_LCD);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;2) &lt;strong&gt;FreeIntChainHandler&lt;/strong&gt;&lt;br /&gt;&gt; This function unloads an existing interrupt handler.&lt;br /&gt;&gt; Parameters: handle of the installed ISR.&lt;br /&gt;&gt; Return value: TRUE/FALSE.&lt;br /&gt;&gt; Code of the ISR will not be freed from memory until reset.&lt;br /&gt;&gt; Sample code: &lt;span style="color:#000099;"&gt;FreeIntChainHandler(hIISR);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;3) &lt;strong&gt;KernelIoControl&lt;/strong&gt;&lt;br /&gt;&gt; This function provides the kernel with a generic I/O control for carrying out I/O operations.&lt;br /&gt;&gt; Will use this function to call IOCTL_HAL_REQUEST_SYSINTR to map IRQ-to-SYSINTR.&lt;br /&gt;&gt; Will call IOCTL_HAL_RELEASE_SYSINTR also.&lt;br /&gt;&gt; Parameters: IOCTL code, Out &amp; In buffer.&lt;br /&gt;&gt; Return value: TRUE/FALSE.&lt;br /&gt;&gt; Sample code:&lt;br /&gt;&lt;span style="color:#000099;"&gt;DWORD dwSYSINTR, dwIRQ = IRQ_LCD;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#000099;"&gt;KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &amp;dwIRQ, sizeof(dwIRQ), &amp;amp;dwSYSINTR, sizeof(dwSYSINTR), NULL);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;4) &lt;strong&gt;KernelLibIoControl&lt;/strong&gt;&lt;br /&gt;&gt; This function is called by a driver to communicate with an interrupt handler.&lt;br /&gt;&gt; Parameters: ISR handle, OEM or ISV specified IOCTL, ...&lt;br /&gt;&gt; Return value: TRUE/FALSE (ERROR: Use GetLastError() to retrieve)&lt;br /&gt;&gt; This function will call IOControl function implemented in the interrupt handler.&lt;br /&gt;&gt; Sample code:&lt;br /&gt;&lt;span style="color:#000099;"&gt;GIISR_INFO iisr_info;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#000099;"&gt;memset(&amp;iisr_info, 0, sizeof(GIISR_INFO));&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#000099;"&gt;iisr_info.SysIntr = dwSYSINTR;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#000099;"&gt;if (!KernelLibIoControl(hIISR, IOCTL_GIISR_INFO, &amp;iisr_info, sizeof(iisr_info), NULL, 0, NULL)) &lt;/span&gt;&lt;br /&gt;&lt;span style="color:#000099;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#000099;"&gt;RETAILMSG(1, (TEXT("KernelLibIoControl failed!\r\n")));&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#000099;"&gt;//...&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#000099;"&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;5) &lt;strong&gt;BusTransBusAddrToStatic&lt;/strong&gt;&lt;br /&gt;&gt; This function translate a bus address to a system address. Then, it creates a static, process independent, virtual address mapping for that address.&lt;br /&gt;&gt; Parameters:&lt;br /&gt;- hBusAccess: handle obtained from CreateBusAccessHandle&lt;br /&gt;- InterfaceType: Bus type&lt;br /&gt;- BusNumber: bus number where the device resides.&lt;br /&gt;- BusAddress: bus-relative address of registers and ports on the device.&lt;br /&gt;- Length: number of bytes to map on the device.&lt;br /&gt;- AddressSpace: flag&lt;br /&gt;- MappedAddress: virtual address mapped.&lt;br /&gt;&gt; Return value: TRUE/FALSE&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Related Functions in OAL&lt;/strong&gt;&lt;br /&gt;1) &lt;strong&gt;NKCallIntChain &lt;/strong&gt;&lt;br /&gt;&gt; This function is called by OEM from the OAL ISR routine (such as OEMInterruptHandler).&lt;br /&gt;&gt; This function determines which chained or shared interrupt device triggered an IRQ event.&lt;br /&gt;&gt; Parameter: IRQ value.&lt;br /&gt;&gt; Return value: return SYSINTR_CHAIN if no ISR has handled the IRQ event, otherwise return valid SYSINTR value to the OEM, and OEM passes back this value to kernel to trigger IST. &lt;/div&gt;&lt;div align="justify"&gt;&gt; Sample code: &lt;span style="color:#000099;"&gt;DWORD dwSysIntr = NKCallIntChain(nIrq);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;2) &lt;strong&gt;OALIntrTranslateSysIntr&lt;/strong&gt;&lt;br /&gt;&gt; This function returns the list of IRQs for a specified SYSINTR. It will be called by OEMInterruptEnable, OEMInterruptDisable &amp; OEMInterruptDone function.&lt;br /&gt;&gt; Parameters: SYSINTR value, buffer for the IRQs list&lt;br /&gt;&gt; Return value: TRUE/FALSE&lt;br /&gt;&lt;br /&gt;3) &lt;strong&gt;OALIntrEnableIrqs&lt;/strong&gt;&lt;br /&gt;&gt; This function enables the list of interrupts identified by an IRQ.&lt;br /&gt;&gt; Parameters: number of IRQs in the list, Pointer to the list of IRQs.&lt;br /&gt;&gt; Return value: TRUE/FALSE&lt;br /&gt;&lt;br /&gt;4) &lt;strong&gt;OALIntrDisableIrqs&lt;/strong&gt;&lt;br /&gt;&gt; This function disables the list of interrupts identified by an IRQ.&lt;br /&gt;&lt;br /&gt;5) &lt;strong&gt;OALIntrDoneIrqs&lt;/strong&gt;&lt;br /&gt;&gt; This function scans the list of identified by an IRQ, signaling the end of interrupt processing.&lt;br /&gt;&lt;br /&gt;6) &lt;strong&gt;OEMInterruptHandler&lt;/strong&gt;&lt;br /&gt;&gt; This function is called by the kernel when an interrupt occurs. This function is only used by the ARM kernel, and provides all ISR functionality for ARM-based platforms. You do not need to call HookInterrupt in OEMInit for ARM-based platforms.&lt;br /&gt;&gt; Parameters: instruction counter when the interrupt occurred.&lt;br /&gt;&gt; Return value: a SYSINTR_* value.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Related Functions in an Installable ISR DLL&lt;/strong&gt;&lt;br /&gt;Installable ISR DLL must implement the following functions:&lt;br /&gt;1) &lt;strong&gt;DllEntry&lt;/strong&gt;&lt;br /&gt;&gt; DllEntry is a placeholder for the library-defined function name. You must specify the name you use when you build your DLL.&lt;br /&gt;&lt;br /&gt;2) &lt;strong&gt;CreateInstance&lt;/strong&gt;&lt;br /&gt;&gt; This function is implemented by an ISR to return a value that references an instance of the ISR. It's the DLL's first function called when the &lt;em&gt;LoadIntChainHandler&lt;/em&gt; function is called to install the ISR handler, after the handler is loaded.&lt;br /&gt;&gt; Parameters: none&lt;/div&gt;&lt;p&gt;&gt; Return value: a reference value that identifies an instance of the ISR handler, -1 identifies an error in the ISR.&lt;br /&gt;&lt;br /&gt;3) &lt;strong&gt;DestroyInstance&lt;/strong&gt;&lt;br /&gt;&gt; This function is called when an installable ISR is unloaded using the &lt;em&gt;FreeIntChainHandler&lt;/em&gt; function.&lt;br /&gt;&gt; Parameters: instance of the ISR being unloaded.&lt;br /&gt;&gt; Return value: TRUE/FALSE.&lt;br /&gt;&lt;br /&gt;4) &lt;strong&gt;ISRHandler&lt;/strong&gt;&lt;br /&gt;&gt; This function prototype is used by an OEM/IHV to create and export an installable interrupt handler.&lt;br /&gt;&gt; Parameters: Instance of the ISR being registered.&lt;br /&gt;&gt; Return value: the SYSINTR value that corresponds to the IST that should be schedule to run. This can also include returning SYSINTR_CHAIN if the IRQ is not handled by your handler.&lt;br /&gt;&lt;br /&gt;4) &lt;strong&gt;IOControl&lt;/strong&gt;&lt;br /&gt;&gt; This function, exported by the installable ISR DLL, enables a communication path from the interrupt service thread (IST) to the ISR.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Notes about the Installable ISR DLL&lt;/strong&gt;&lt;br /&gt;1) The DLL is loaded into the kernel process space.&lt;br /&gt;2) The DLL must be in the FILES section with no fixup variable or in the MODULES section with the kernel flag, K, set for a kernel-style fixup variable. A fixup variable is functionality of ROMIMAGE that allows you to initialize a global variable in the NK.exe at MAKEIMG time.&lt;br /&gt;3) The DLL can contain more than one ISR handler and can be used in several call to LoadIntChainHandler. All ISR handlers have a full stack, based on the CPU.&lt;br /&gt;4) The DLL cannot have dependent DLLs.&lt;br /&gt;5) The DLL cannot implicitly to any other DLL, and all code must be contained in the DLL.  You can set NOMIPS16CODE=1 in the &lt;em&gt;sources&lt;/em&gt; file to prevent importing external functions.&lt;br /&gt;6) Must be compiled to eliminate the C Run-Time Library from being included by default.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Samples of the Installable ISR&lt;/strong&gt;&lt;br /&gt;There is a sample of the installable ISR -GIISR in Windows CE under the public\common\oak\drivers\giisr\ folder.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-1316966224060919576?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/1316966224060919576/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=1316966224060919576' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/1316966224060919576'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/1316966224060919576'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2006/09/installable-isr.html' title='Installable ISR'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6448756203283676481.post-7154189724052382004</id><published>2006-09-03T00:10:00.000+08:00</published><updated>2006-12-15T08:19:13.853+08:00</updated><title type='text'>FlashDisk - Flash Translation Layer (FTL)</title><content type='html'>&lt;span style="color:#009900;"&gt;&lt;em&gt;The FlashDisk is designed to fully replace Microsoft FAL for better stability and better performance. The original purpose of designing FlashDisk attributes to that the Microsoft FAL has some unconquerable shortcomings which are the critical features in some hardware dependent system.&lt;/em&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The FlashDisk is a Flash Translation Layer (FTL) which Microsoft named as Flash Abstraction Layer (FAL) used to link with Flash Media Driver (FMD) to make a Flash Block Driver. It is designed to fullly replace Microsoft FAL for better stability and better performace.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Microsoft FAL Known Disadvantages&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;1) Boot time is very long if the large size flash is full filled.&lt;br /&gt;2) Disk may be crashed if power failure suddenly during data write process. And this will cause system can not boot up any longer if the crashed part lies in the hive-based registry area. We often have to face this issue reported by our QA engineer.&lt;br /&gt;3) Read/Write performance is not well-pleasing.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;FlashDisk Advantages&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;1) Quick Boot - Boot up very quickly even large size disk is full filled.&lt;br /&gt;2) Read/Write performance is better than MS FAL driver.&lt;br /&gt;3) Power failure is safe.&lt;br /&gt;4) Better and more controllable wear-leveling policy.&lt;br /&gt;5) Better bad block management arithmetic.&lt;br /&gt;6) Automatic Garbage Collection.&lt;br /&gt;7) Memory usage is acceptable.&lt;br /&gt;8) Can replace MS FAL fully.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Performance Comparison&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The following is a simple comparison between FlashDisk and the Microsoft FAL performance. The test platform is: 200MHz ARM920 based processor; WinCE4.2 OS; K9F1208+TC58NVG (every 2048 page is divided to four 512 pages) NAND Flash; BINFS Partition Size: 22MB, Data Partition Size: 162MB; Read/Write Performance Test App: Use 1MB buffer to R/W 5MB file 10 times.&lt;br /&gt;1) Boot time&lt;br /&gt;FlashDisk: 10s (empty), 10s (full)&lt;br /&gt;MS FAL: 10s (empty), &lt;span style="color:#cc0000;"&gt;35s&lt;/span&gt;(full)&lt;br /&gt;2) Read/Write speed:&lt;br /&gt;FlashDisk: R: 3563KB/s, W: 816KB/s (empty), R: 2966KB/s, W: 658KB/s (full)&lt;br /&gt;MS FAL: R: 2138KB/s, W: 598KB/s (empty), R: 1854KB/s, W: 459KB/s (full)&lt;br /&gt;3) Stability:&lt;br /&gt;4) Memory:&lt;br /&gt;5) CPU loading:&lt;br /&gt;6) Bad block management:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Usage&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;1. Copy the FlashDisk.lib, FlashDisk.pdb to your nandflash driver path.&lt;br /&gt;2. Modify the sources file in which linked with microsoft FAL.lib:&lt;br /&gt;a) Remove: $(_COMMONOAKROOT)\lib\$(_CPUINDPATH)\FAL.LIB \&lt;br /&gt;b) Add: &lt;flashdisk&gt;&lt;flashdisk&gt;&lt;flashdisk&gt;&lt;flashdisk&gt;\$(_CPUINDPATH)\FlashDisk.lib \&lt;br /&gt;c) Modify line: DLLENTRY=DllEntry to DLLENTRY=DllMain&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Remarks&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;To use FlashDisk, the following constraints must be followed (also these constraints are compatible with Microsoft FAL):&lt;br /&gt;1) All blocks used by OEM must have the &lt;em&gt;&lt;span style="color:#cc0000;"&gt;OEM_BLOCK_RESERVED&lt;/span&gt;&lt;/em&gt; flag (recommend to set &lt;em&gt;OEM_BLOCK_READONLY&lt;/em&gt; and bad block flag, but they are optional). These blocks begin from the head of the NAND flash and include NBOOT, TOC, EBOOT, ...&lt;br /&gt;2) If you use monolithic IMAGE, the blocks used by IMAGE also should have at least set the &lt;em&gt;&lt;span style="color:#cc0000;"&gt;OEM_BLOCK_RESERVED&lt;/span&gt;&lt;/em&gt; flag.&lt;br /&gt;3) If your system have BINFS partition, every block of the BINFS partition should have the &lt;em&gt;&lt;span style="color:#cc0000;"&gt;OEM_BLOCK_READONLY&lt;/span&gt;&lt;/em&gt; flag.&lt;br /&gt;4) If you want to try FlashDisk, please comment here or send mail to me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6448756203283676481-7154189724052382004?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/7154189724052382004/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=7154189724052382004' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/7154189724052382004'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/7154189724052382004'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2006/09/flash-block-driver-flashdisk.html' title='FlashDisk - Flash Translation Layer (FTL)'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6448756203283676481.post-6269942238731910578</id><published>2006-09-02T09:56:00.000+08:00</published><updated>2006-09-02T09:59:31.135+08:00</updated><title type='text'>Scatter Loading Mechanism in ADS</title><content type='html'>&lt;em&gt;&lt;span style="color:#009900;"&gt;Origin of this article: we have falled arcoss one requirement that some functions of the booter loader project need to build to another bin file and execute in the known fixed address. This is something like the DLL in the windows system but it is compiled by ADS. After I study the ADS linker guider I know that just using more than one load region can resolve this problem. &lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;Scatter loading is a mechanism provided by the ARM linker, which enables you to partition an executable image into regions that can be positioned independently in memory.&lt;br /&gt;&lt;br /&gt;In a simple embedded computer system, memory is divided into ROM and RAM. The image produced by the linker is divided into the "Read-Only" segment, which contains the code and read-only data, and the "Read-Write" segment, which contains the initialized and non-initialized or zero-initialized (ZI) data. Usually, the "Read-Only" segment is placed in ROM and the "Read-Write" segment is copied from ROM to RAM before execution begins.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger2/7489/787201684971151/1600/scatter1.6.jpg"&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://photos1.blogger.com/blogger2/7489/787201684971151/400/scatter1.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="CLEAR: both; PADDING-BOTTOM: 0.25em"&gt;Embedded systems often use a more complex memory map, which can consist of ROM, SRAM, DRAM, FLASH and so on. The scatter loading mechanism lets you place various parts of the image in these distinct memory areas.&lt;br /&gt;&lt;br /&gt;Scatter loading enables you to partition your program image into several regions of code and data which can be placed separately in the memory map. Each region is placed in a contiguous chunk of memory space. The location of a region can differ between load time and execute time, which the application copying code and data from its load address to its execution address.&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger2/7489/787201684971151/1600/scatter2.1.jpg"&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://photos1.blogger.com/blogger2/7489/787201684971151/400/scatter2.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The placement information is contained in a description file, the name of which is passed as a command line parameter to the linker.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Load Regions and Execution Regions&lt;/strong&gt;&lt;br /&gt;A program image consists of regions which may occupy different locations at load time and execution time.&lt;br /&gt;&lt;br /&gt;This means that just before an image is executed, there are some regions which need to be moved from the locations at which they were initially loaded in memory. For example, initialized read-write data may reside in ROM, but it must be copied into RAM when the program starts executing.&lt;br /&gt;There are two mechanisms available to describle where image regions should be placed in memory at execution time:&lt;br /&gt;1) Using -RO and -RW command line options.&lt;br /&gt;2) Scatter loading&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Scatter Loading Definitions&lt;/strong&gt;&lt;br /&gt;1) Load region&lt;br /&gt;The memory which is occupied by a program before it starts executing, but after it has been loaded into memory, can be split into a set of disjoint load regions, each of which is contiguous chunk of bytes.&lt;br /&gt;2) Execution region&lt;br /&gt;The memory used by a program while it is executing can also be split into a set of disjoint execution regions.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Placing Regions with Scatter Loading&lt;/strong&gt;&lt;br /&gt;1) Use the command line options &lt;em&gt;"-scatter descritption-file"&lt;/em&gt;, this option will cause the linker to ignore the &lt;em&gt;"-RO -RW"&lt;/em&gt; options.&lt;br /&gt;2) Scatter load images can be output in the following formats:&lt;br /&gt;&lt;strong&gt;BIN&lt;/strong&gt;&lt;br /&gt;Generates one file for each load region, in the directory given as the output filename. These can then be blown into ROM, Flash and so on as appropriate. The output name is treated as a directory name. Each load region is placed in a separate file in that directory, with the same name as the load region. Load region names must therefore not contain characters, or be of a length, unacceptable to the host file system.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;ELF&lt;br /&gt;&lt;/strong&gt;Generates a single executable ELF file suitable for loading into the debugger. A single output file, containing one section per load region, is produced. The name of the file is given by the -output option.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Linker pre-defined symbols &lt;/strong&gt;&lt;br /&gt;Using the region names given in the scatter loading description file, the linker generates the symbols required to allow each region to be copied from its load address to its execution address.&lt;br /&gt;Neither the linker nor the C library provide the code required to copy an execution region from its load address or create a zero-initialized region; you must do this, as the application code writer.&lt;br /&gt;&lt;br /&gt;The linker generates symbols which allow your routine to initialize all the execution regions that have different load and execution address. These symbols give the length, load address and execution address of each region.&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger2/7489/787201684971151/1600/scatter3.jpg"&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://photos1.blogger.com/blogger2/7489/787201684971151/400/scatter3.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;For RO and RW segments:&lt;br /&gt;Load$$region_name$$Base is the load address of the region&lt;br /&gt;Image$$region_name$$Base is the execution address of the region&lt;br /&gt;Image$$region_name$$Length is the execution region length in bytes&lt;br /&gt;For zero-initiailized segments:&lt;br /&gt;Image$$region_name$$ZI$$Base is the execution address of the region&lt;br /&gt;Image$$region_name$$ZI$$Length is the execution region length in bytes.&lt;br /&gt;These symbols can be imported and used by assembly language programs, or referred to as extern address from C (using the -fc compiler option which allow $ in identifiers).&lt;br /&gt;&lt;br /&gt;Note&lt;br /&gt;These symbols are generated for every region named in the scatter load description.&lt;br /&gt;A scatter load image is not padded with zero, and requires the ZI data area to be created dynamically. This is similar to the case with a normal -bin file when the -nozeropad option is used. There is therefore no need for a load address symbol for ZI data.&lt;br /&gt;The linker sorts AREAs within execution regions according to their attributes. For example, all initialized data area are grouped together. Therefore, you can assume that all initialized data that needs coping is contiguous.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Area ordering&lt;/strong&gt;&lt;br /&gt;The linker orders AREAs within each execution region by attributes. The ordering is:&lt;br /&gt;Read-only code&lt;br /&gt;Read-only based data&lt;br /&gt;Read-only data&lt;br /&gt;Read-write code&lt;br /&gt;Based data&lt;br /&gt;Other initialized data&lt;br /&gt;Zero-initialized data&lt;br /&gt;The pseudo-attributes FIRST and LAST can be used in the description file to mark the first and last AREAs in an execution region if the placement order is important (for example, if the ENTRY must be first and a checksum last).&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Scatter loading and long distance branching &lt;/strong&gt;&lt;br /&gt;The ARM instruction set has branch instructions that allow a branch forwards or backwards up to 32Mb. The BL (Branch with Link) instruction also preserves the return address in register 14 (Link Register, LR).&lt;br /&gt;&lt;br /&gt;The Thumb instruction set has much shorter branch ranges. From 256 bytes in the case of conditional branches to 2048 bytes for unconditional branches. The BL instruction has a range of 4Mb.&lt;br /&gt;&lt;br /&gt;The linker has to ensure that no branch or subroutine call violates these range restrictions. If you place your execution regions in such a way as to require inter-region branches beyond the range, the linker generates an error stating Relocated value too big for instruction sequence.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The description file&lt;/strong&gt;&lt;br /&gt;A Scatter Load Description is a text file describing how the AREAs in a linked image are assigned to separate regions of memory.&lt;br /&gt;In a scatter load description&lt;br /&gt;. You list the separate regions of memory in which your image will execute, and specify an execution base address of each region.&lt;br /&gt;. You describe how execution regions are packed into regions of physical memory (called load regions). The linker generates a separately loadable chunk of image for each load region. In some image formats (for example BIN), each load region is written to its own output file; In others (for example ELF, AIF), each load region has its own section within a single output file. You can think of each load region corresponding to a separate persistent memory such as ROM, EPROM, FLASH, and so on.&lt;br /&gt;. Using simple patterns and attributes you describe how armlink should assign the constituent AREAs of your image to execution regions.&lt;br /&gt;&lt;br /&gt;Notes:&lt;br /&gt;. If you want to execute a code region directly then you must ensure its execution address is the same as its load address. Consequently, you must assign the AREA containing your image's ENTRY point to such a region.&lt;br /&gt;. Your scatter load description does not describe the objects which make up your image. You describe that in the same way for all image on its command line. The patterns you write in a scatter load description describe how to assign the AREAs which armlink has already selected to the execution regions you defined.&lt;br /&gt;. You can describe execution regions which overlap, provided that you give each region the OVERLAY attribute. If you do this, the linker generates support code and data to allow overlapping regions to be swapped dynamically at execution time and adds a reference from the support code to an overlay manager. You must have included ARM's standard overlay manager, or one compatible with it, in your list of object files.&lt;br /&gt;. ARM-Thumb interworking veneers are built an AREA called IWV$$Code, You can assign this AREA to an execution region just like any other area using the AREA selector:&lt;br /&gt;*(IWV$$Code)&lt;br /&gt;Although there is no associated module, * still matches. Because there is only one IWV$$Code AREA, this section is unambiguous. &lt;/div&gt;&lt;div style="CLEAR: both; PADDING-BOTTOM: 0.25em"&gt;&lt;/div&gt;&lt;div style="CLEAR: both; PADDING-BOTTOM: 0.25em"&gt;&lt;strong&gt;Example of the scatter loading file:&lt;/strong&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger2/7489/787201684971151/1600/scatter4.1.jpg"&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://photos1.blogger.com/blogger2/7489/787201684971151/400/scatter4.1.jpg" 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/6448756203283676481-6269942238731910578?l=bhduan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bhduan.blogspot.com/feeds/6269942238731910578/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6448756203283676481&amp;postID=6269942238731910578' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/6269942238731910578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6448756203283676481/posts/default/6269942238731910578'/><link rel='alternate' type='text/html' href='http://bhduan.blogspot.com/2006/09/scatter-loading-mechanism-in-arm.html' title='Scatter Loading Mechanism in ADS'/><author><name>Alex Duan</name><uri>http://www.blogger.com/profile/15244282872460872564</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>
