2007年6月23日 星期六

[舊文] bash shell script 程式設計

這是三年前寫的舊文嘍~ 放在這懷舊一下



bash shell script 程式設計(序言,1,2,3,4,5,6,完)

發表 bash shell script 程式設計(序言,1,2,3,4,5,6,完)
相信所有玩過 Unix的人都會同意 shell script 是一個十分強大的工具,可以用來幫助自已在短時間內解決許多枯\躁而乏味的工作,而且讓工作變得有趣。
對於 shell script 要怎麼寫,為什麼會想到這麼寫?對於這個問題,我個人的答案是:用多了,就知道了。有時很聰明的想法,往往是靈機一動,就想到了。我會建議大家,如果寫了好用的 script 就把他留下來,給個好名字。有時候用得上時,就會很高興有這個自製的工具。
當然,要寫 script 之前,要先了解一些東西。
1. 資料流
>, >> , < , | , #&># .....
2. 一些好用的工具
cat
grep
awk
sed
find
more
........ everything you can use.
3. 變數
4. 指令代換
5. 判斷式
if else fi
6. 流程控制
while for
....
在之後的幾篇文章中,我會慢慢把一個個 topic 寫完...
希望不會寫得太糟 Razz



tick 在 星期五 二月 06, 2004 12:11 am 作了第 8 次修改
星期六 一月 17, 2004 12:42 am




發表 資料流
UNIX是第一個支援資料流的作業系統。
什麼是資料流呢?
就是把程式的輸入和輸出想像成一個串流,
在 Unix 之下,任和一個一般的程式都會直接開三個檔案。
0. stdin
1. stdout
2. stderr
這三個檔案分別是 資料流的 輸入和輸出,及錯誤輸出

stdin ====> 程式 =====> stdout
        ∟==> stderr

在 default 之下,stdin 是接著 keyboard
stdout 是接著 tty (你想成 monitor 就好了)
stderr 也是接著 tty


資料流既然是"流",那當然可以轉向。
"<" 這個指令呢就是把 stdin 接上後面的檔案 如 cat <>" 是把 stdout 寫入後面的 file
如檔案內有東西,會把檔案內的東西清空才寫入。

">>" 和 ">" 相同,但不會把檔案內的東西清空,而是寫在檔尾
如

cat test.txt >> foo

"|" (pipe)這個呢則是把前面的stdout 接到後面程式的 stdin
如
cat test.txt | more
這樣, cat 的輸出就可以被 more 接下來。

> >> 還可以把 stderr 轉到 stdout
如
2>&1
也可把 stdout 轉到 stderr
如
1>>&2

在 shell script 中資料流轉向,和pipe 是十分常用的技巧
(應該說是基本工夫)
在一般下指令的時候也是很常用上
如
cat pbsd.c | grep CONFIG_PBS

有時候如果要做一些比較複雜的動作。接個四五個 pipe 再加上轉向,也不為過

--
過年期間我不能上網,所以我會在自己的 notebook 寫,等回台北再 post 上來

星期日 一月 18, 2004 1:45 am



如果有好的能力,沒有好的工具,那也是沒有用,但很幸運的是,
之前的 Unix Programer 寫了許多方便自己的工具,相同的那些工具\r
也能方便我們。
下面是一些工具的簡單介紹。(都可用 pipe 和轉向)
cat :
  把檔案打開,印到 stdout 上
grep :
   grep 是一個在輸入資料中找出指明要找的字串的那一行文字的工具。
  如
   grep "I Love Shell Script" test.txt
   就是把 test.txt 這個檔案中,有 "I Love Shell Script" 這個字串的那一行印>到
  stdout 中。
  cat test.txt | grep "I Love Shell Script" #也是一樣的
awk :
  一個用來分析內文的工具,它可以掃描文章內容,找出你要的文字,且
  依你的要求做輸出,你可以把它當做 grep 的加強版。
  awk 的語法很像 C 語言,所以對會寫 C 語言的人而言,這是一個很好用的工具
  如
  awk '{print NR,$0}' text.txt
  就會把 text.txt 的內容印出來,且加上行數
sed :
  這個工具可以幫你把你想換掉的字串一次換掉

awk 和 sed 這兩個工具是十分強大的工具,它們可以做到的事十分的多
遠比它一開始被定義時所想到的功能還多,多到可以寫一本書來談。\r
O'Reilly 就有出一本 awk & sed 的書,有興趣的話可以找一本來看看。

find:
  這個工具可以依你的要求,找出你想要的檔案,在系統管理上很好用。
  可是依時間,大小,檔名,修改時間等等的選項來找檔案。

more (less) :
  把 stdin or 檔案內容分成一頁一頁的來看,一般來說, less 比較強一些。
  可以支援 vi 的語法,但目前 more 也一一支援了。

以上每個工具都是十分好用的工具。
但我沒有詳細的談,詳細的東西呢,你可以用 man 這個工具來看。
如
man find
然後你就會了解為什麼我只說一下它們的功能了 Smile

星期二 一月 27, 2004 11:34 am




發表 變數 參數
在 bash 中設定變數很容易
不用指定形態
直接指定就可以了
如
myvar="I love linux."
就是指定 myvar 這個變數為 "I love linux." 這個字串
使用這個變數呢,則是用 $myvar 來使用
如
echo $myvar

如想對 變數做運算,可用 let
let "expression"

如 let i=i+1

在 shell script 中,可以在 script 加上參數
而參數會依你所打入的指令依序定義
如有一個script 叫 showme
#!/bin/bash
# filename showme
echo $0
echo $1
echo $2

執行結果如下
>./showme abc def
./showme
abc
def

如果要 show出所有參數,可以 $* 表之。
要知道參數數量,可以 $# 表之
$$ 為 script 執行時的 pid


--
寫著寫著,有一些東西不清楚,找了一下 man
發現 man 寫得真是清楚極了。

上 google 查了一下,有一個網頁整理的很好
http://www.fanqiang.com/a4/b1/index_b.html
看來我可以不用寫了 QooQ

星期二 二月 03, 2004 12:47 am



發表 指令代換
在 bash 之中 我們可以用 ` command` 來執行指令,且將其視為一個整體,最後的結果為全部的結果
例如
ls -alF `find -size 0`
就是找出所有 size == 0 的檔案
將之結果當做是 ls -alF 的參數
這個技巧在 shell 之中很常見如
NumberOfFiles=`find | wc -l`
就是把 find | wc -l 這結果指定為 NumberOfFiles 的值

星期三 二月 04, 2004 10:27 pm



發表 判斷式
shell script 是一個完整的語言,當然會有 if else 等等的指令
就讓我們來看看如何使用 bash shell 的 判斷式 吧

在這裏我是假設大家會使用某種程式語言。

格式是如下的

if expression; then
  list
elif list; then
   list
else
  list
fi

這裏的 list 代表是一個或一堆指令的集合。
expression 代表的是一個會有return 值的指令。

如expression 不為空,或 0 就表示為 true
fi 代表 這個 if 結束了 如同 C 語言的 }
then 就如同 C 語言的 {

elif 後面的 list 會依序執行,到了最後如不為空,或 0 就為真 也就是再執行後面的 list

對於 expression 如要寫判斷式 有兩種格式
1. (( expression ))
這個格式等同於 let "expression"
這就是把 expression 內的資料做計算
例如
(( $abc + 1 ))
2. [[ expression ]]
這個格式等是可以比較這個 expression 的兩邊
如
[[ $1 == "abc" ]]
如果相同,就為 1 否則為 0
比較的運算子有 == != ! && ||
== 是全等
!= 不等
! not 運算子
&& and 運算子
|| or 運算子
如
( (( $# > 3 )) && [[ $1=="abc" ]] && ( [[ $2!="def" ]] || ![[ $3=="ghi" ]]) )

一個例子
if (( $#==0 )) ; then
echo "usage: xxx [xxx | xxxx]"
else
 if ( [[ $1 != "xxx" ]] && [[ $1 != "xxxx" ]] ) ; then
  echo "prometer [xxx | xxxx]"
  exit
 fi
 if [ $1 = "xxx" ]; then
  ....
 else
  ........
 fi
fi

星期三 二月 04, 2004 11:00 pm



發表 流程控制
在程式之中,for 和 while 讓我們省下了很多的力氣

在 bash shell 之中 for 和 while 的用法如下
for:
在bash 中 for 的用法有兩種
for name [ in word ] ; do list ; done
for (( expr1 ; expr2 ; expr3 )) ; do list ; done
第一種是從 字串的array 中拿出一個,成為 name (name 為變數)
再進入迴圈中,直到array 中的字拿完為止 (list 為迴圈內容)

第二種就很像 C 語言了, 第一次跑時,一開始 run expr1
再 check expr2
跑完 list 後 跑 expr3 再跑 expr2
一旦expr2 的結果是 0 or 空 就跳離


while:
while 的用法
while list_a ; do list_b; done
當 list_a 的最後一個 command 結果不為 0 或 空之時,就進入迴圈做 list_b

until:
until list_a; do list_b; done
和 while 相反,當 list_a 的最後一個 command 的結果不為 0 或空時,離開迴圈。

還有一些東西 如 select case esac 等... 這些東西可以用 if for or while 組合而成,就不再說明了。

星期四 二月 05, 2004 11:40 pm




發表 put all together
說了那麼多,我們開始來寫寫 bash shell script 吧
就拿之前post 過的 chout 為例子好了

首先,一始開寫 shell script 的人很有可能不知道如何執行 shell script
假設我們有一個 shell script 叫 chout 已經寫好了
我們有兩個方法可以執行它
1. bash chout
這個方法是執行一個 bash ,且叫它讀入 chout 並執行
2. 在 chout 的第一行加入 #!/bin/bash
(告訴你的shell 這個 shell script 指定用 bash)
再 chmod a+x chout
(指定 chout 為一個可執行檔)
之後你就可以把 chout 當一個程式來使用了。

讓我們來看看這個例子
01 #!/bin/bash
02 if (( $#==1 )) ; then
03  ares=`find -name '*.c'`
04  ares="$ares `find -name '*.h'`"
05 else
06   ares=`find -name $2`
07 fi
08 for arrs in $ares
09 do
10  if [ -f $arrs ] && (( `cat $arrs | grep -i $1 | wc -l` > 0 )); then
11   echo "In file $arrs"
12   cat $arrs | awk '{print "#"NR"\t"$0}' | grep -i $1
13   echo " "
14  fi
15 done

01 行告訴我們,這是一個 bash 的程式
02 $# 是變數的數量,也就是 : 若 變數的數量為 1 則做 03 04 否則做 06
03 把 "find -name *.c" 這個指令的結果存在ares 中
04 ares 再加上 find -name *.h 的結果
06 找 名字為第二個參數的檔案,且存成 ares
08 在 ares 中依序抓出一個元素,命之為 arrs ,如抓完了,做 15 行的下一行(沒有了,就是結束了)
09 10~14 是迴圈範圍
10 當 $arrs 是檔案 ( [ ] 是 test 的簡寫 (有興趣請看 man test)) 且 $arrs 有大於一行包涵 第一個參數的話,做 11~13
11 應該不用解釋吧
12 為$arrs 中的內容加上行號,只 show 出有 $1 的行
13 印空白行

 
以上只是一個小小的 shell script
因為 shell script 不用 compile ,只要隨手改改,隨手寫寫就能用。
不用考慮太多形態的問題,所有程式都是指令。都是 可用的function
所以在使用上很方便,只要多加一點點巧思,就可以用一點點的時間,做出一些很炫的東西。
試著玩玩看吧,保証 linux 功力會大增喔!!

Self Unit Test Framework

自我測試架構
適用語言: OOP language

相信大家都知道軟體測試的重要,也明白軟體測試有助於開發者及早發現問題。
軟體測試之中有相當多的面向,而今天我要提的,是 Unit Test 這個部分。

在 OOP 的語言之中,每個元件應該有其一獨特且專一個功能 (如此才能彰顯 OOP 的優勢)
也就是說,在寫 OOP 的案子時,到最後應該會像是在玩樂高一般。把每個元件兜到它應該出現的位置。案子也就成了。

但,這只是個理想。

實際作做案子就會知道,程式一定有 bug ,而要如何 debug 就成了每個設計師的惡夢。而debug 中最最另人頭疼的,就是不知道 bug 在那。
Unit Test 就是一個很有效且快速的技術幫助設計師了解且找出問題的所在。
在表面上,做 Unit Test 看起來會多花許多工夫。不過,在案子越來越龐大時, Unit Test 可以快速的指出問題的癥結,也可以讓 PM 更明確的掌握案子的進度。
一般來說,使用 Unit Test 技術可以讓案子穩定的有進展。

在使用 Unit test 之前要了解幾件事。
1.你的物件是要做什麼的。
2.有那些 boundary 存在?
3.錯誤情況的處理為何?
4.任何你的物件會遇到的極端狀況

再依上述的認知做以下的 Test
1. 正常的 input 資料是否有正常的 output (要先知道正確的結果)
2.在 boundary 時資料是否也是正常運作 lower/upper bound 都要做
3.不正常的 input 時,是否能發現,且做出正確的回應?
4.大量被使用時,是否能成功的運作?

在做測試時,你要用最嚴苛的心去測你的程式。這才是正真對你自己仁慈。

每個物件都要有一個自己的測試程式,每做一次修改(不管多小的修改),就要跑一次,並得到一份報告。

如果物件被整合到其它物件,其它的物件也要做 Unit test
最懶也是最好的方法就是寫支小 script 一次跑完所有的 Tests
(好像很花時間?其實不然,因為它可能會在很短的時間內幫你找出本來可能要花一個月才找出來的 bug)


以下是小弟寫的 Unit Test FrameWork (可輕易的改寫成 Java 版的 :-) )
每個要被測試的物件,只要多重繼承 SelfTestUnit
然後實作下面兩個 functions
virtual bool doSelfTest() {return false;};
把你對這個物件的測試寫在裏面,並回報是否測試成功

virtual const char *myClassName(){return "Please Set ClassName Here";};
指定這個物件的名字 (for report)

而在測試程式之中寫:
Capataz cap;
cap.addSelfTester(new 被測試的物件(1));
cap.addSelfTester(new 被測試的物件(2));
cap.addSelfTester(new 被測試的物件(3));
...
cap.doTest();

就可以了...




File: selftest.h

#ifndef __TICK_CPP_SELF_TEST_FRAMWORK__
#define __TICK_CPP_SELF_TEST_FRAMWORK__

#include <vector>

class SelfTestUnit {
public :
virtual bool doSelfTest() {return false;};
virtual const char *myClassName(){return "Please Set ClassName Here";};
};

class Capataz {
public :
//Capataz(char *file);
//~Capataz();
bool addSelfTester(SelfTestUnit *);
bool addSelfTester(SelfTestUnit &);
bool delSelfTester(SelfTestUnit *);
bool delSelfTester(SelfTestUnit &);
bool doTest();
private:
std::vector < SelfTestUnit * > _tester;
void testReport(SelfTestUnit *,bool );
void allPassReport(bool);
};


#ifdef SELFPROFILE
#include <stdlib.h>
#include <stdlio.h>
extern "C" void __cyg_profile_func_enter(void *func,void *caller) __attribute__((__no_instrument_function__));
extern "C" void __cyg_profile_func_exit(void *func,void *caller) __attribute__((__no_instrument_function__));
#endif //SELFPROFILE

#endif // __TICK_CPP_SELF_TEST_FRAMWORK__




File: selftest.cpp

#include <iostream>
#include "selftest.h"


bool Capataz::addSelfTester (SelfTestUnit * tester) {
if (tester == NULL) {
std::cout << "Try to register a NULL pointer" << std::endl;
return false;
}
_tester.push_back (tester);
return true;
}

bool Capataz::addSelfTester (SelfTestUnit & tester) {
return addSelfTester (&tester);
}

bool Capataz::delSelfTester (SelfTestUnit * tester) {
std::vector < SelfTestUnit * >::iterator pos;
if (tester == NULL) {
std::cout << "Try to remove a NULL pointer" << std::endl;
return false;
}
for (pos = _tester.begin (); pos < _tester.end (); pos++) {
if (tester == *pos) {
_tester.erase (pos);
return true;
}
}
return false;
}

bool Capataz::delSelfTester (SelfTestUnit & tester) {
return delSelfTester (&tester);
}

bool Capataz::doTest () {
bool allpass = true;

std::vector < SelfTestUnit * >::iterator pos;
if (_tester.size () == 0) {
std::cout << "There are no tester yet!!" << std::endl;
return allpass;
}

bool btmp;

for (pos = _tester.begin (); pos < _tester.end (); pos++) {
std::cout << "Do Testing:" << (*pos)->myClassName () << std::endl;
btmp = (*pos)->doSelfTest ();
allpass = allpass && btmp;
testReport ((*pos), btmp);
}
allPassReport (allpass);
return allpass;
}


void Capataz::testReport (SelfTestUnit * stu, bool rep) {
if (rep) {
std::cout << "Test Report: " << stu->myClassName () << "--->OK!!" << std::endl;
} else {
std::cout << "Test Report: " << stu->myClassName () << "--->Failed!!" << std::endl;
}
}

void Capataz::allPassReport (bool rep) {
std::cout << std::endl;
if (rep) {
std::cout << "All Passed? Yes" << std::endl;
} else {
std::cout << "All Passed? No" << std::endl;
}
}

[舊文]陶笛 DIY 心得圖

因為陶韻的資料不見了,只好把以前的東西搬來這裏 @_@
慘~ 過去點點滴滴的回憶啊~

post at:
2005/08/29 17:29


[舊文]陶笛DIY 時的想法

舊文回 po ,因為陶韻的資料不見了,把它放到這來嘍

星期一 十月 17, 2005 7:56 pm 文章主題: DIY 時的一些....想法 引言回覆
也許應該放在閒聊板 0_O

剛剛才用榔頭敲掉了一隻花了很多心血、長得很美的笛子
原因無它,"音色不夠好",而且又被我修壞掉了

當決定要把它回收重作之時,內心其實是天人交戰的。
那隻笛子是我彷是誠的外型,做日式十二孔笛。
外型真的很美,可惜內空間沒挖好,又想用調音的調到我想要的調性
調到了,音色也毀了。

這陣子,作了好幾把笛子,在每把笛子中都灌注了多少的心血,感情。
每當一把笛子第一次發出聲音之時,總是有一種莫名的感動,就好像聽到新生兒第一次啼哭,任何人都會因此而感動…之後慢慢地從單音變成十幾個不全的音,再慢慢的一個音一個音的相對音準慢慢確立。如果幸運的話,它會從黑黑的笛子慢慢變成灰白色…此時它已經能吹奏出許多的曲子。它已經有強烈的個性,有它的優缺點。
出來的不見得是我所預期的個性,不見得是我要的音色,但每一支都讓我收獲不少。對於"陶笛"這樣東西又有更深入的體會,對於每種性質的平衡又有更深的體悟。

把笛子拿去燒,又是另一次的浴火重生,每當決定安排一次燒笛,總是會在腦海裡幻想燒出來會有什麼樣的花紋,啊~~這到目前我為是沒辦法有效的掌握…也會怕燒壞了…這時的每一隻笛子早就和我有深厚的感情,早就帶給我無窮的歡樂。往往在燒之前,都是以訣別的眼神看著它們,先做好最壞的打算。所以燒成後,總是有一種重生的感覺。

陶笛 DIY 入門真的不難,只要你有正確的工具,有點耐心,有點幸運,要一隻陶笛嗚嗚叫真的不難。
難,是難在於進階之後。要高音漂亮?低音漂亮?音色乾淨?共鳴好?聲音哄亮?有無氣聲?音是不是夠準?每個音的氣量是否平均?是否好演奏?外型好不好看?……

時至今日,學作陶笛大約半年的時日,回想起剛開始做陶笛之時,才做了幾把,就以為可以做出很好的笛子,深深覺得好笑

手下那把破碎不堪的土笛,在幾個月前,我可能會把它封成 "演奏級" 的笛子,而現在卻是期待它的轉生。

陶土就是這麼可愛,當你不滿意時,總是個可以再來一次 ^.^

2007年6月11日 星期一

Linux kernel 之 list_head

Linux Kernel 是世上的 Hacker 們留給世人一份極為珍貴的資產。
然而 Kernel 卻又是如此的龐大,要一下子了解整個 Kernel 實在不容易。

不過,有個有趣的進入點也是一個好的開始。

在大型的系統之中,必定會有大量的資量要處理,儲存...
處理資料的效率和可靠性會強烈的影響一個作業系統的表現。

在這裏 Linux 使用了一個很漂亮,而且相當強大的手法來實作 double link list

它放在 include/linux/list.h

這個東西,其實小弟在三年多前就寫了一篇文章談它
不過那時只是很簡略的談了一這個工具的用法。沒有深入的討論它背後的技術。


list_head 是一個很簡的 struct ,內容如下
struct list_head {
struct list_head *prev,*next;
};

沒錯,它就是這麼的簡單。 list_head 的內容就是兩個 list_head 的指標 (pointer 註一)
我們可以把它想像成一個鉤環,可以把它安裝在任何結構之中。
例如:

struct ANY_STRUCTURE {
int A;
int B;
struct list_head head_1;
char *C;
struct list_head head_2;
}
在這個例子之中 ANY_STRUCTURE 包涵了兩個 list_head 的實體
如下圖所示:


只要稍微想一下,不難發現 head_1 head_2 的 prev 和 next 可以輕易的指到任何 list_head 的位址上。

而當我們有一個結構的定義時,我們就能算出各個 field 在結構中的相對位址。
也就是說 head_1 相對於 struct ANY_STRUCTURE 的位址是 sizeof(int) * 2
而 head_2 的位址是 sizeof(int)*2 + sizeof(struct list_head) + sizeof(char *) 註二

也就是,如果我有一 head_1 的位址,我就可以算出包涵這個 head_1 的ANY_STRUCTURE 的位址了。
設計 head_1 的位址為 ptr,則 ANY_STRUCTURE 的位址是
==> ptr - ((structure ANY_STRUCTURE *)0)->head_1
在這裏,我們把位址 0 當做是 structure ANY_STRUCTURE 的指標,而它指相的 head_1 的 offset 就是 ANY_STRUCTURE 到 head_1 之間的 offset

也就是說,我可以間接從 head_1 或 head_2 的位址得到 ANY_STRUCTURE 的位址。

在 Linux kernel 之中,就利用 list_head 的 prev next 指向 前一個,及後一個 list_head 的物件的位址,和同一串 list 中的物件都為相同結構。就可以不用搬資料,只控制指標的快速對任何 type 的結構做操作。


註一:小弟習慣把 pointer 的中文翻成指標,有些人會翻成指針…有相當多的名字…在這知道指的是 pointer 就好了

註二:在 kernel 之中,因為各種機器的架構不同,我們不可以預設一個基本變數的長度。

2007年5月30日 星期三

tty / console, printf/printk strange bug in s3c2440

In Linux 2.6.21 with s3c2440 CPU may encounter a confusing condition
Console works perfectly after setting console=ttySAC1 115200 at init parameter.
(may also need to set ucon ulcon ufcon DIV and clk well first)

But the output of busybox is terrible bad, even not recognizable.
It will be something like that :


Creating 3 MTD partitions on "NAND 128MiB 3,3V 8-bit":
0x00000000-0x00600000 : "Boot Agent"
0x00840000-0x01240000 : "PNXX Linux Root FS"
0x01780000-0x06980000 : "PNXX Linux Home FS"
mice: PS/2 mouse device common for all mice
i2c /dev entries driver
VFS: Mounted root (jffs2 filesystem) readonly.
Freeing init memory: 76K
B
.
[m

#
#

Input is OK but output is a disaster.
Strangely printk is also works perfectly @. @

This is because tty write to register S3C2410_UTXH too fast, and all data jams.
And the console on the other hand waits UART TX ready (s3c24xx_serial_console_txrdy(port, ufcon))
and therefore console works well. (So that printk works well)

To solve this problem we can use:
------------------------------------

Index: drivers/serial/s3c2410.c
===================================================================
--- drivers/serial/s3c2410.c (revision 16)
+++ drivers/serial/s3c2410.c (working copy)
@@ -83,5 +83,5 @@
#include
#include
+#define TICK_DEBUG
#include // add by tick
/* structures */

@@ -403,15 +403,19 @@
return IRQ_HANDLED;
}

+static void s3c24xx_serial_console_putchar(struct uart_port *port, int ch);
+
static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
{
struct s3c24xx_uart_port *ourport = id;
struct uart_port *port = &ourport->port;
struct circ_buf *xmit = &port->info->xmit;
+ unsigned int ufcon;
int count = 256;

if (port->x_char) {
wr_regb(port, S3C2410_UTXH, port->x_char);
+ //debug("\nport->x_char='%c'\n",port->x_char);
port->icount.tx++;
port->x_char = 0;
goto out;
@@ -431,8 +435,11 @@
while (!uart_circ_empty(xmit) && count-- > 0) {
if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
break;
-
- wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
+#ifdef TICK_DEBUG
+ s3c24xx_serial_console_putchar (port, xmit->buf[xmit->tail]) ;
+#else
+ wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]); // TICK REMOVE for debug
+#endif
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
}

------------------------------------------
using console putchar to deal with it.


Beware there is another problem,
s3c24xx_serial_console_putchar used a static valiable "cons_uart"
In this case is OK.
However, we should write another putchar command in which we can define our port and let s3c24xx_serial_console_putchar use the new putchar function.

2007年5月28日 星期一

新玩具


昨天拿到兩隻鍚口笛,C 調及 D 調。

跟著小唐的 漫步莎莉花園 吹奏,心情相當的好。
http://www.youtube.com/watch?v=v313Uc-iZpc