2013年9月14日 星期六

作業系統之前的程式 for stm32f4discovery (5) - pendsv interrupt

目的是要喚起 pendsv 這個 isr, 這個程式碼其實不難, 原理也不複雜, 可是卻花了好大功夫才搞定。

L41 ~ 43, L51 ~ 53, 在設定 priority, 預期在 svc_isr 之後, 要跳進 pendsv_handle。在 svc_isr 設定 pendsv 的 pending bit, 等著離開 svc_isr 之後被喚起。

嘗試很久都無法喚起 pendsv_handle, 都無法成功, 我甚至還另外寫了一個 c 的版本, c 的版本順利 work, 終於讓我找到問題。

問題是 ... 沒有問題, 這個程式從頭開始就是對的, 只是 pendsv_handle 並不是在離開 svc_isr 後立刻執行, 而是在過了一段時間之後才執行。真是奇怪阿!

由於這緣故, 讓我多花了好幾天解決這問題。

程式碼註解中有提到可 dump 哪些暫存器來觀察, 你有和我買一樣的書會很方便, 沒有的話就看:
Cortex™-M3 Technical Reference Manual (filename:DDI0337E_cortex_m3_r1p1_trm.pdf)

pendsv.S
  1 # test pendSV handler and systick
  2 
  3 .equ STACK_TOP, 0x20000800
  4 .text
  5 .global _start
  6 .code 16
  7 .syntax unified
  8 _start:
  9   .word STACK_TOP, start
 10   .type start, function @ let lsb to 1
 11   .word int_isr+1
 12   .word int_isr+1
 13   .word int_isr+1
 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 svc_isr+1 @ svc isr
 21   .word int_isr+1
 22   .word int_isr+1
 23   .word pendsv_handle+1
 24   .word systick_isr+1
 25   .word int_isr+1
 26   .word int_isr+1
 27   .word int_isr+1
 28 
 29 start:
 30 
 31   @ ref:  arm cortex-m3: 嵌入式系統設計入門 p8-10
 32 @  ldr r0, =0xe000ed0c
 33 @  ldr r1, =0x05fa0500
 34 @  strb r1, [r0]
 35 @
 36 @ ref: @ Cortex™-M3 Technical Reference Manual (file name: DDI0337E_cortex_m3_r1p1_trm.pdf)
 37 @    System Handler Priority Registers (p8-27)
 38   @ pendsv priority
 39 
 40 
 41   ldr r0, =0xe000ed22
 42   mov r1, #0xff
 43   strb r1, [r0]
 44 
 45   @ systick priority
 46   ldr r0, =0xe000ed23
 47   mov r1, #0xff
 48   strb r1, [r0]
 49 
 50   @ svc priority
 51   ldr r0, =0xe000ed1f
 52   mov r1, #0xff
 53   strb r1, [r0]
 54 
 55 
 56 @ systick setting
 57 #if 0
 58 @ 0xe000ed24 check systick isr active
 59 @ 0xe000e018 check systick count
 60   ldr r0, =0xe000e010 @ control reg
 61   mov r1, #0
 62   str r1, [r0]
 63   ldr r1, =0x3fff
 64   str r1, [r0, #4]
 65   str r1, [r0, #8]
 66   mov r1, #0x7
 67   str r1, [r0] @ enable systick
 68 #else
 69   svc 0
 70 #endif
 71 
 72 @  cpsie i
 73 
 74 @ watch 0xe000ed24, 0xe000ed04 ref: arm cortex-m3: 嵌入式系統設計入門 p8-9
 75   mov r1, #0x33
 76 deadloop:
 77   mov r1, #0x22
 78   b deadloop
 79 
 80 pendsv_handle:
 81   movs r2, #0x12
 82   nop
 83   bx lr
 84 
 85 svc_isr:
 86   push {r4-r11, lr}
 87 #if 1
 88   @ enable pendsv ref: STM32F207 高性能网络型 MCU 嵌入式系统设计 p 412
 89   ldr r0, =0xe000ed04 
 90   ldr r1, [r0]
 91   orr r1, #0x10000000
 92   str r1, [r0]
 93 #endif
 94   nop
 95   movs r3, #0x56
 96   pop {r4-r11, pc}
 97   #bx lr
 98 
 99 systick_isr:
100   PUSH    {R14}
101   @ enable pendsv ref: STM32F207 高性能网络型 MCU 嵌入式系统设计 p 412
102   ldr r0, =0xe000ed04 
103   ldr r1, [r0]
104   orr r1, #0x10000000
105   str r1, [r0]
106   movs r0, #0x98
107 @  bx lr
108   POP     {R14}
109 
110 int_isr:
111   nop
112   movs r1, #0xf
113 @  push {r1}
114   bx lr
115 
116 .data
117 .space  0x200, 0
118 psp_stack_top:
119 
120 .space  0x400, 0
121 msp_stack_top:
122 

以下為  gdb trace 的結果, 在 svc_isr, pendsv_handle 我加入一些說明。

gdb.result
 1 descent@descent-u:stm32f4_prog$ arm-none-eabi-gdb -x g.sh 
 2 GNU gdb (Sourcery CodeBench Lite 2012.03-56) 7.2.50.20100908-cvs
 3 Copyright (C) 2010 Free Software Foundation, Inc.
 4 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
 5 This is free software: you are free to change and redistribute it.
 6 There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
 7 and "show warranty" for details.
 8 This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-none-eabi".
 9 For bug reporting instructions, please see:
10 <https://support.codesourcery.com/GNUToolchain/>.
11 Breakpoint 1 at 0x7c: file pendsv.S, line 89.
12 Breakpoint 2 at 0x74: file pendsv.S, line 82.
13 start () at pendsv.S:41
14 41        ldr r0, =0xe000ed22
15 (gdb) c
16 Continuing.
17 Note: automatically using hardware breakpoints for read-only addresses.
18 
19 Breakpoint 1, svc_isr () at pendsv.S:89
20 89        ldr r0, =0xe000ed04 
21 (gdb) x/1xw 0xe000ed04
22 0xe000ed04:     0x0000080b
23 (gdb) x/1xw 0xe000ed24
24 0xe000ed24:     0x00000080
進入 svc_isr 之後, dump 0xe000ed04, 0xe000ed24
從 0xe000ed04/0xe000ed24 register 知道 svc 正在執行
25 (gdb) n
26 90        ldr r1, [r0]
27 (gdb) n
28 91        orr r1, #0x10000000
29 (gdb) n
30 92        str r1, [r0]
31 (gdb) n
32 94        nop
33 (gdb) n
34 95        movs r3, #0x56
35 (gdb) x/1xw 0xe000ed04
36 0xe000ed04:     0x1000e80b
37 (gdb) x/1xw 0xe000ed24
38 0xe000ed24:     0x00000080
set pendsv pend bit, L28 
39 (gdb) n
40 96        pop {r4-r11, pc}
41 (gdb) n
42 start () at pendsv.S:75
43 75        mov r1, #0x33
44 (gdb) n
45 deadloop () at pendsv.S:77
46 77        mov r1, #0x22
47 (gdb) n
48 78        b deadloop
49 (gdb) n
50 77        mov r1, #0x22
51 (gdb) n
52 78        b deadloop
53 (gdb) n
54 77        mov r1, #0x22
55 (gdb) n
56 78        b deadloop
57 (gdb) n
58 77        mov r1, #0x22
59 (gdb) c
60 Continuing.
61 
62 Breakpoint 2, pendsv_handle () at pendsv.S:82
63 82        nop
離開 svc_isr 進入 deadloop 後才跳到 pendsv_handle 
64 (gdb) n
65 83        bx lr
66 (gdb) x/1xw 0xe000ed04
67 0xe000ed04:     0x0000080e
68 (gdb) x/1xw 0xe000ed24
69 0xe000ed24:     0x00000400
得知 pendsv 正在執行 
70 (gdb) n
71 deadloop () at pendsv.S:77
回到 deadloop 
72 77        mov r1, #0x22
73 (gdb) n
74 78        b deadloop
75 (gdb) n
76 77        mov r1, #0x22
77 (gdb) n
78 78        b deadloop
79 (gdb) c
80 Continuing.
81 ^C
82 Program received signal SIGTRAP, Trace/breakpoint trap.
83 deadloop () at pendsv.S:77
84 77        mov r1, #0x22

你一定會有點疑惑, 為什麼要介紹這個對吧!嗯 ... 讓我賣個關子。

ref:

沒有留言:

張貼留言

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

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