2013年9月17日 星期二

作業系統之前的程式 for stm32f4discovery (6) - systick

和一般 stm32 書上的介紹不同, 我不想只單純的呼叫廠商寫好的 library, 這只要有手就會了, 你只想學到這樣的程度而已嗎?應該和我一樣不會滿足這樣的學習方式吧!我想搞懂到底是如何設定中斷, systick register, 參考別人的程式碼自然是最快的, 這是 scmrtos 的 systick 程式碼。

Ports/CortexM3/GCC/OS_Target_asm.S
.weak  __init_system_timer
__init_system_timer:

    LDR     R1, =NVIC_SYSPRI15      // Set the SysTick exception priority (lowest)
    LDR     R2, =NVIC_ST_PRI
    STRB    R2, [R1]

    LDR     R1, =NVIC_ST_RELOAD     // Setup SysTick
    LDR     R2, =(SYSTICKFREQ/SYSTICKINTRATE-1)
    STR     R2, [R1]
    LDR     R1, =NVIC_ST_CTRL       // Enable and run SysTick
    LDR     R2, =(NVIC_ST_CTRL_CLK_SRC | NVIC_ST_CTRL_INTEN | NVIC_ST_CTRL_ENABLE)
    STR     R2, [R1]
    BX      LR

Ports/CortexM4F/GCC/OS_Target_cpp.cpp
#pragma weak __init_system_timer
extern "C" void __init_system_timer()
{
        SysTickPriority = 0xFF;
        SysTick->LOAD = SYSTICKFREQ/SYSTICKINTRATE-1;
        SysTick->CTRL = NVIC_ST_CTRL_CLK_SRC | NVIC_ST_CTRL_INTEN | NVIC_ST_CTRL_ENABLE;
}


Ports/CortexM4F/GCC/OS_Target_cpp.cpp
// SysTick stuff
struct systick_t
{
    uint32_t       CTRL;
        uint32_t       LOAD;
        uint32_t       VAL;
        uint32_t const CALIB;
};

enum
{
    NVIC_ST_CTRL_CLK_SRC = 0x00000004,       // Clock Source.
    NVIC_ST_CTRL_INTEN   = 0x00000002,       // Interrupt enable.
    NVIC_ST_CTRL_ENABLE  = 0x00000001        // Counter mode.
};

systick_t volatile * const SysTick = (systick_t volatile * const)0xE000E010UL;

基本上只要參考這 3 個 register (0xe000e010, 0xe000e014, 0xe000e018), 設定完成後, systick isr 就可以工作了。以下是我自己的測試程式。

ref: L36 ~ L43, 這個程式應該不需要多做說明, 翻開這本書 arm cortex-m3: 嵌入式系統設計入門 p8-12, 對照一下就知道了。或是 Cortex™-M3 Technical Reference Manual p 8-8 (file name: DDI0337E_cortex_m3_r1p1_trm.pdf)

 x/1xw 0xe000e018 可以看到這個值會倒數, 變成 0 時就會呼叫 systick_isr。使用 gdb break point 會暫停倒數。

systick.S
 1 # test 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 int_isr+1
21   .word int_isr+1
22   .word int_isr+1
23   .word int_isr+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-12
32 @ 0xe000e010, 0xe000e014, 0xe000e018
33 @ systick setting
34 @ 0xe000ed24 check systick isr active
35 @ 0xe000e018 check systick count
36   ldr r0, =0xe000e010 @ control reg
37   mov r1, #0
38   str r1, [r0]
39   ldr r1, =0x3fff
40   str r1, [r0, #4]
41   str r1, [r0, #8]
42   mov r1, #0x7
43   str r1, [r0] @ enable systick
44
45 @ watch 0xe000ed24, 0xe000ed04 ref: arm cortex-m3: 嵌入式系統設計入門 p8-9
46   mov r1, #0x33
47 deadloop:
48   mov r1, #0x22
49   b deadloop
50
51 systick_isr:
52   PUSH    {lr}
53   mov r0, #0x05
54   mov r1, #0x27
55   @bx lr
56   POP     {pc}
57
58 int_isr:
59   nop
60   movs r1, #0xf
61 @  push {r1}
62   bx lr

快了, 終於接近我要做的東西了。

arm cortex-m3: 嵌入式系統設計入門第 14 章 systick 計時器有更進階的說明, bit[31] 可以檢查是否有外部時脈來源可以當然 systick 時脈。8-13 表 8-12 校正暫存器 (0xe000e01c)

沒有留言:

張貼留言

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

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