2007年9月9日 星期日

74164串接線路

74164是很好用的元件,可以拿來擴充I/O,還能串接起來使用,非常方便
程式碼實現也非常容易。(但需注意評估 bit shift 造成周邊硬體元件的影響)
底下是基本的串接線路圖。

2007年8月8日 星期三

多核的幾個方便用途

FPPA 八核常常只用到4-5個就很夠了,下的 CPU 可以拿來作別的用途~蠻方便的…
一、當成硬體訊號輸入模擬
 例如~模擬回授信號,一個純的無雜訊信號,方便驗證其它核心程式的正確性。
二、當成系統監測 CPU
 隨時監看系統狀況,必要時透過 RS232 即時傳回系統狀態。
三、拿來校正系統時脈
四、拿來唱歌
…有想到再補充

2007年8月2日 星期四

Melody 音調

昨天我在已經跑了 6 個核的 FPPA 上多加了可以反應按鍵並發聲的程式~
只用了不到一分鐘,結果非常滿意,不止聲音好、即時、還能在背景執行(形容成這樣蠻貼切的)~

底下各音階個音符的頻率:
音階 Do Re Mi Fa So La Si
低音 頻率
(Hz) 131 147 165 175 196 220 247
中音 頻率
(Hz) 262 294 330 349 392 440 494
高音 頻率
(Hz) 522 587 659 700 784 880 988

讓MCU發聲,這讓我想到了之前寫 PIC 程式的一些心得…
以前寫慣了 Windows 程式,總是習慣於用事件的處理方式來寫作,當某個條件觸發時才會去作處理。
有點類似 MCU 的 interrupt 處理方式~中斷來了或 timer 到了才去作特定的事。
事實上這樣子寫作也確實比較條理分明,有的負責處理狀態的變化、有的負責處理該作的事、有的負責時序的變化,CPU在不同的狀態之間飛舞,一切都在你的預料之中…
初寫 PIC 也是用這樣子的方式來寫程式~寫起來很快~難只難在一些時序的計算光用腦袋想像是不夠的~(這時有個示波器什麼都能迎刃而解)~再怎麼寫跑起來也是八九不離十,比起複雜的AP程式,某些地方來講 MCU 的程式確實是非常簡單~(呵~當然是在不考慮硬體的情況下)
但是這樣子的情況在卻被一個簡單的嗶嗶聲給崩解~
問題關鍵點是:
1.我需要定時用掃描的方式去作輸出(例如掃LED DISPLAY數字出來)
2.我還要在有按鍵按住時持續發出嗶~~~的音調
在PIC,我用TIMER中斷來製造1,我用POOLING的方式來偵測按鈕的動作,同時在按住時,持續發聲。
程式看起來沒問題~跑起來卻完全不是想像那樣美妙= ="
發出來的聲音是破破的~聽的出來有斷斷續續~LED也看的到閃閃動人= =
搞了 N 種方法~努力嚐式去均擔、固定住兩邊的時序~而過程跟結果卻都是非常惱人~"~
顧了這邊掉了那邊~時序怎麼橋就是橋不順~
最後是妥協了~為了發出正常的聲音,在按鍵時只得將LED先關掉~(結果證明聲音比較重要,搞不好還沒人意識到LED燈不見了)
回想起來~也算是一場惡夢了= =" (還不是自己功力太差才這樣 = =" )

現在覺得~有多核可以用還真是幸福~

2007年7月26日 星期四

FPPA 多執行緒?

這兩天看到這篇文章 Coroutine in FPPA,寫有關於用同一顆 CPU 來跑不同 TASK 的問題。
突然也靈機一動,想來試試這樣子的機制可以用在哪邊~

答案是~多執行緒~Time Sharing

把一個CPU當成四個來用,靠TIMER中斷來控制PC頁的切換~
可惜由於中斷只有FPP0能產生,所以只能作用在FPP0~
不過,要切成幾個分時的TASK基本上都沒有問題~嘿~有趣了。

測試的中間也發現一個有趣的問題,delay 這個指令由於不是一個指令周期就能完成(同時 acc 遞減),導致有可能delay到一半被 swap out,再回來時 PC 又重回到了delay上(acc又重置),結果就是 delay 不完。
解決的方法目前想到的就是暫時把中斷關掉嘍。(安全起見)

另一個問題,萬一 time slice 小於一個指令周期的話,會造成類似上面的情形,指令尚未完成,PC還沒來的及往後加,就被 swap out,再回來又回到了原點,結果就是一個指令永遠也跑不完。

這樣子的狀況代表的意義很值得深入去探討,也就是關係到 fppa 核心硬體設計上的特性~
於是會不會有一種可能,太快的 timer interrupt 或 time slice 的大小~造成「不正常的」swap out?

解決的方式可能還有待進行各種不同的試驗才會知道,應當是可以調整到切出固定的 time slice 出來(正確來講是分配到同樣多的指令周期),當然如果你的要求不是很嚴苛的話,那只要確保能往下跑也就ok了。

另外一種解決方式,就是用 internal interrupt 的方式來由各 task 控制把自己的執行權讓出來,這也是可行,不過好像就少了那種味道了。

至於是不是還有其它更多問題? 我想要實際拿來用才知道了。

不過話說回來,也蠻懷疑這樣大費周張的效益倒底有多大,因為畢竟八核己經很夠用了,而且除非要寫的程式要控制的事項非常的煩多,才會突顯出它的便利性吧?


// ======== START RAM Define ========
.ramadr 0x00
word nousePC;
word task0PC;
word task1PC;
word task2PC;
word task3PC;
word t16index;
int taskno;
// ======== END RAM Define ========

// ======== START FPPA ========
.romadr 0x0000
goto fpp0Boot;
goto fpp1Boot;
goto fpp2Boot;
goto fpp3Boot;
goto fpp4Boot;
goto fpp5Boot;
goto fpp6Boot;
goto fpp7Boot;
// ======== END FPPA ========

// ======== START Interrpt Service Routine ========
.romadr 0x0010
mov a, 0xFF; /// 第一次產生中斷,stack裡的pc是無用的
ceqsn taskno, a;
goto switch01;
popw nousePC;
pushw task0PC; /// 準備切到task0 pc
goto switchOk;
switch01:
mov a, 0;
ceqsn taskno, a;
goto switch12;
popw task0PC; /// 保存好task0 PC
pushw task1PC; /// 準備切到task1
goto switchOk;
switch12:
mov a, 1;
ceqsn taskno, a;
goto switch23;
popw task1PC; /// 保存好task1 PC
pushw task2PC; /// 準備切到task2
goto switchOk;
switch23:
mov a, 2;
ceqsn taskno, a;
goto switch30;
popw task2PC; /// 保存好task2 PC
pushw task3PC; /// 準備切到task3
goto switchOk;
switch30:
mov a, 3;
ceqsn taskno, a;
goto switchOk;
popw task3PC; /// 保存好task3 PC
pushw task0PC; // /準備切到task0
switchOk:
inc taskno; /// 記錄目前task編號-遞增循環
mov a, 0b00000011;
and taskno, a;
stt16 t16index ; /// 重置 Time Slice
set0 intrq.2;
reti;
// ======== END Interrpt Service Routine ========
fpp0boot:
// -------- START FPPA Boot Setting --------
///...略
// -------- END FPPA Boot Setting --------
// -------- START Interrupt initial setup --------
mov a, 0x00;
mov intrq, a; /// clear interrpt reqest register
mov a, 0b00000100;
mov inten, a; /// enable Timer16 interrupt
// -------- END Interrupt initial setup --------

// -------- START Timer16 initial setup --------
mov a, 0x00; /// timer 16 is up-count
mov lb@t16index, a ; ///Time Slice
mov a, 0x00;
mov hb@t16index, a ;

mov a, 0b10010000 ;
mov t16m, a ; /// Set OSC/Prescale
// -------- END Timer16 initial setup --------

// -------- START variables initialize --------
mov a, la@Task0;
mov lb@task0PC, a;
mov a, ha@Task0;
mov hb@task0PC, a;

mov a, la@Task1;
mov lb@task1PC, a;
mov a, ha@Task1;
mov hb@task1PC, a;

mov a, la@Task2;
mov lb@task2PC, a;
mov a, ha@Task2;
mov hb@task2PC, a;

mov a, la@Task3;
mov lb@task3PC, a;
mov a, ha@Task3;
mov hb@task3PC, a;

mov a, 0xFF;
mov taskno, a;
// -------- END variables initialize --------

/// Enable ALL FPP !!
mov a, 0b11111111;
mov fppen, a ;

/// Stack Pointer Setting for fpp0
mov a, 0x60;
mov sp, a;

stt16 t16index ;
engint;
goto $; /// Idle... waitting first interrupt
Task0:
tog LED0;
goto Task0;
Task1:
tog LED1;
goto Task1;
Task2:
tog LED2;
goto Task2;
Task3:
tog LED3;
goto Task3;

不同速度各 CPU 同步的問題

在不同時脈下工作的 CPU,例如在 pmode=0 的模式 fpp0(/2) fpp1(/8)
假設 fpp0 的 1T=1us、那麼 fpp1 的 1T=4us…

程式碼A:
fpp0:
delay unknown_cycles
set0 signal
goto fpp0
fpp1:
wait0 signal
set1 signal
goto fpp1

問題:fpp1 在 wait 的時候是每 4us 去檢查一次 signal 或者是每 1us 就會檢查一次(或更即時?) 並且往下跑 ? (這影響到 fpp1 頻率固定的問題)

實際測試結果==>

使用 ICE 單步追蹤的結果是 wiat 指令是按當時 CPU 的指令周期來算的,fppa1每 4us 才會檢查一次signal ~(真正的晶片應該也是?)

於是底下程式碼就有可能變成 fpp1 always waitting。(因為每次去檢查都不巧被設為1)

程式碼B:
fpp0Loop:
set0 signal;
set0 signal;
set1 signal;
goto fpp0Loop;

fpp1Loop:
wait0 signal;
// do something
goto fpp1Loop;

再回頭看原來的程式碼A…
程式碼A的 fpp1 有可能在檢查 signal 之前剛好 signal 被設為 0
也可能在檢查 signal 之後的 3us 之內 signal 才被設為 0,於是有了誤差。

相反的,若是快的 cpu 等慢的 cpu 也會有搶到拍子的情況發生。

結論==>
 這應該是屬於 fppa 硬體上的特性,程式設計師自己要小心留意到的一個問題。

2007年7月22日 星期日

簡單的按鈕防彈跳程式碼

 wait1 BTN0;
call Delay;
t1sn BTN0;
goto $-3;
// TODO: button down
wait0 BTN0;
call Delay;
t0sn BTN0;
goto $-3;
// TODO: button release

2007年7月21日 星期六

FPPA 副程式區城變數的問題(結語)

這樣子的結果,感覺還不錯

雖然還不確定在實際應用面能起多大作用

但是,至少在多了一種控制多 cpu 的方式

可以預見,在一些場合,會須要有類似這樣子的(先後)機制

譬如,一個專司 LCM 模組的 cpu,就不能隨機的接受輸出,不然輸出會不成樣…

當然,這些是必須要花一些 cpu 成本的,(大約7-8個指令周期)

而且,可能會有不確定性~(的等待時間)

再者,這也只是自己試的一個方法,還沒有完整的驗證過(包括硬體層面)

說不一定在怎樣的情況下會造成打死結的情況~!?

VirtualBox 空間減肥

sdelete64 -z c: VBoxManage  modifymedium  disk  "/Users/fellow/VirtualBox VMs/Win10/Win10.vdi"  --compact *.vdi 路徑可以在 VirtualBox 儲...