2013-04-27

Learning ARM Assembly in Raspberry Pi - 2

經過了第一次的試煉Learn ARM Assembly in Raspberry Pi,發現組合語言其實沒想像中的難,反倒是花了不少時間才弄懂GPIO的spec,尤其是Function Select及Pin Output Set/Clear那部份。第一次的練習讓ACT燈恆亮,接下來加點花俏的功能,讓它閃爍。

修改main.s的內容如下:

.section .init
.globl _start
_start:

ldr r0,=0x20200000

mov r1,#1
lsl r1,#18
str r1,[r0,#4]

/* <#1> */
loop$:
mov r1,#1
lsl r1,#16
str r1,[r0,#40]

/* <#2> */

mov r2,#0x3f0000
wait$:
sub r2,#1
cmp r2,#0
bne wait

/* <#3> */
mov r1,#1
lsl r1,#16
str r1,[r0,#28]


/* <#4> */
mov r2,#0x3f0000
wait2$:
sub r2,#1
cmp r2,#0
bne wait2

b loop$



說明:

<#1>
在這段之前的程式碼不變,而這一段落也只加了loop$,這個區段的tag。

<#2>
打開16th pin的開關後,維持一小段時間,再把16th pin的開關關掉,再等待一段時間再打開,如此反覆即可達到閃爍的效果。這一段程式碼的目的就是等待,但是目前還沒用到計數器,只是很單純的暴力解法,設定一個值,然後一直減1減1直到變成0等待結束,這樣的寫法非常直觀,但是不能保證每次的時間間隔是固定的。

使用mov在r2中填入0x3f0000的值,接著設定一個wait$的tag,用sub將r2的值減去1,然後用cmp比較目前r2的值跟0之間的大小,最後用bne反覆執行wait$的內容。bne是指令b的變形,b可以想成是執行,而bne則是有條件的執行,代表當上一次比較結果不一致時則執行,b + not equal = bne。所以在r2的值不為0的時候會一直反覆減1,直到r2 = 0為止才會跳脫wait$這個區段。

<#3>
這個區段的程式碼跟<#1>相似,差別只在於最後將直寫入的記憶體位址不同,這裡是寫到r0 + 28 bytes的地方,而不是r0 + 40 bytes。目的是要將16th pin的Output Set值設定為1,藉此將ACT燈關掉。

<#4>
這個區段跟<#2>意義相同,差別只在於tag不同,因為tag的名稱不能重複,如此而已。這種寫法看起來很蠢,程式碼重複但不能重用,在此先牛刀小試一番,之後再改成聰明的寫法。最後再回到loop$的開頭重新執行,這樣就能使ACT燈一明一滅,非常有趣,當然也可以讓明滅等待的時間不同。

同樣回到Template目錄,執行make編譯,將編譯產生的kernel.img複製到SD卡上取代原本的kernel.img。
Post a Comment