2013年10月26日 星期六

process switch for stm32f4discovery (0) - 小試身手

x86 process switch 系列後, 我嘗試實作 arm cm3 的 process switch, 基本原理是一樣的, 不過 stack 處理可讓我傷透腦筋, 也才有 x86 process switch implementation (1.5) - save/restore in real mode 這篇, 算是意外的收穫, 腦筋只要動, 還是想得出方法。

不過這篇是在還沒想到之前寫的, 完成後固然開心, 但這不是在 arm cm3 的作法, 實際上的作法有點不同 (類似 1.5 那篇)。但是這方法很容易理解, 還是值得說明一下, 來看看沒有保存 stack 的作法。

source code: https://github.com/descent/stm32f4_prog
git commit b78cb69ce5b61421d0ea865939a983930e1f3fea

process.S
  1 # test svc software interrupt
  2 # ref : http://tw.m.wretch.yahoo.com/blog/DreamYeh/888788
  3 # comment: #, @
  4 
  5 .equ STACK_TOP, 0x20000800
  6 .text
  7 .global _start
  8 .code 16
  9 .syntax unified
 10 _start:
 11   .word STACK_TOP, start 
 12   .type start, function @ let lsb to 1
 13 
 14   .word int_isr+1
 15   .word int_isr+1
 16   .word int_isr+1
 17   .word int_isr+1
 18   .word int_isr+1
 19   .word int_isr+1
 20   .word int_isr+1
 21   .word int_isr+1
 22   .word int_isr+1
 23   .word int_isr+1 @ svc isr
 24   .word int_isr+1
 25   .word int_isr+1
 26   .word int_isr+1
 27   .word int_isr+1
 28   .word int_isr+1
 29   .word int_isr+1
 30   .word int_isr+1
 31 
 32 start:
 33   ldr r0, =stack_frame_a
 34 
 35   ldr r1,=#0xfffffff9
 36   str r1, [r0, #20] @ setup lr
 37 
 38   adr r1, proc_a
 39   str r1, [r0, #24] @ setup pc
 40   mov r1, #0x1000000
 41   str r1, [r0, #28] @ setup psr
 42 
 43   @@@@@@@@@@@@@@@@@@@@@
 44 
 45   ldr r0, =stack_frame_b
 46 
 47   ldr r1,=#0xfffffff9
 48   str r1, [r0, #20] @ setup lr
 49 
 50   ldr r1, =proc_b
 51   str r1, [r0, #24] @ setup pc
 52   mov r1, #0x1000000
 53   str r1, [r0, #28] @ setup psr
 54 
 55   @@@@@@@@@@@@@@@@@@@@@
 56   ldr r5, =cur_proc
 57   mov r1, #0
 58   str r1, [r5]
 59 
 60   svc 0
 61 
 62 deadloop:
 63   b deadloop
 64 
 65 .type proc_a, function @ let lsb to 1
 66 proc_a:
 67   movs r0, #1
 68   svc 0
 69   nop
 70   b proc_a
 71 
 72 .type proc_b, function @ let lsb to 1
 73 proc_b:
 74   movs r1, #2
 75   nop
 76   svc 0
 77   b proc_b
 78 
 79 int_isr:
 80   movs r5, #5
 81   ldr r5, =cur_proc
 82   ldr r0, [r5]
 83   cmp r0, #0
 84   ittee eq
 85   ldreq sp,=#stack_frame_a
 86   moveq r1, #1
 87   ldrne sp,=#stack_frame_b
 88   movne r1, #0
 89 
 90   str r1, [r5]
 91   bx lr
 92 .data
 93 
 94 stack_frame_a:
 95 .word 9 @r0
 96 .word 8 @r1
 97 .word 7 @r2
 98 .word 6 @r3
 99 .word 5 @r12
100 .word 4 @lr 
101 .word 3 @pc @ proc_a
102 .word 2 @psr
103 
104 stack_frame_b:
105 .word 1 @r0
106 .word 2 @r1
107 .word 3 @r2
108 .word 4 @r3
109 .word 5 @r12
110 .word 6 @lr
111 .word 7 @pc
112 .word 8 @psr
113 
114 cur_proc:
115 .word 1

一樣有兩個 stack frame (L94 ~ L102, L104 ~ L112), 保存 r0~r3, r12, lr, pc, psr, L33 ~ L53 把 lr, pc, psr, 設定好即可。在 int_isr 只要輪由切換 stack_frame_a, stack_frame_b 的位址到 sp 即可, 如何, 很簡單吧?

在 int_isr return 時, 會根據 stack frame pc 這欄位而跳到那裡執行。執行 svc 0 時, 會把下一個位址紀錄在 stack frame pc 這欄位。這是基本原理。

中斷時 stack 變化請參考 arm cortex-m3: 嵌入式系統設計入門 p9-2。lr 的值可參考 arm cortex-m3: 嵌入式系統設計入門 p9-7。

疑!你沒打算說明阿? 當然阿! 書上有的東西我幹嘛再打一次。

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。