GadgetSeed  0.9.6
systick.c
[詳解]
1 /** @file
2  @brief Cortex-M SysTickドライバ
3 
4  @date 2013.03.10
5  @author Takashi SHUDO
6 */
7 
8 #include "sysconfig.h"
9 #include "asm.h"
10 #include "device.h"
11 #include "device/timer_ioctl.h"
12 #include "interrupt.h"
13 #include "timer.h"
14 #include "tkprintf.h"
15 #include "task/task.h"
16 
17 #include "stm32l1xx_hal.h"
18 
19 static unsigned long long timer_count = 0;
20 
21 static void (* inth_func)(void *sp);
22 
23 /*
24  SysTick割り込みハンドラ
25 */
26 void inthdr_systick(unsigned int intnum, void *sp)
27 {
28  int i;
29 
30  timer_count += GSC_KERNEL_TIMER_INTERVAL_MSEC;
31 
32  for(i=0; i<GSC_KERNEL_TIMER_INTERVAL_MSEC; i++) {
33  HAL_IncTick(); // HALドライバ用
34  }
35 
36  if(inth_func) {
37  inth_func(sp);
38  }
39 }
40 
41 /*
42  SysTick初期化
43  GSC_KERNEL_TIMER_INTERVAL_MSEC(ms)間隔でタイマ割り込み発生
44 */
45 static void start_systick(void)
46 {
47  long clock = HAL_RCC_GetHCLKFreq();
48 
49  HAL_SYSTICK_Config(clock/1000 * GSC_KERNEL_TIMER_INTERVAL_MSEC);
50  tkprintf("System Clock : %ld MHz\n", clock/1000000);
51  /*
52  タイマ割り込みプライオリティが最高になっているので最低に戻し
53  ている。多重割り込みは対応していないので他の割り込みと同じレ
54  ベルにしなければならない
55  */
56  NVIC_SetPriority(SysTick_IRQn, 0);
57 
58  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
59 }
60 
61 /*
62  SysTick停止
63 */
64 static void stop_systick(void)
65 {
66  SysTick->CTRL &= SysTick_CTRL_ENABLE_Msk;
67 }
68 
69 static int systick_register(struct st_device *dev, char *param)
70 {
71  inth_func = 0;
72 
73  register_interrupt(IRQ2VECT(SysTick_IRQn), inthdr_systick);
74 
75  return 0;
76 }
77 
78 static int systick_unregister(struct st_device *dev)
79 {
80  unregister_interrupt(IRQ2VECT(SysTick_IRQn));
81 
82  return 0;
83 }
84 
85 static int systick_ioctl(struct st_device *dev, unsigned int com, unsigned int arg, void *param)
86 {
87  switch(com) {
89  {
90  // GSC_KERNEL_TIMER_INTERVAL_MSEC の分解能以下のms単位の時間を返す
91  int rtn = (SysTick->LOAD - SysTick->VAL)/(HAL_RCC_GetHCLKFreq()/1000);
92  return rtn;
93  }
94  break;
95 
97  {
98  unsigned long long utime = (timer_count * 1000)
99  + (SysTick->LOAD - SysTick->VAL)/(HAL_RCC_GetHCLKFreq()/1000000);
100  *((unsigned long long *)param) = utime;
101  return 0;
102  }
103  break;
104 
105  case IOCMD_TIMER_START:
106  start_systick();
107  return 0;
108  break;
109 
110  case IOCMD_TIMER_STOP:
111  stop_systick();
112  return 0;
113  break;
114 
115  case IOCMD_TIMER_SETFUNC:
116  inth_func = (void (*)(void *))param;
117  return 0;
118  break;
119 
120  default:
121  SYSERR_PRINT("Unknown ioctl(%08lX)\n", com);
122  return -1;
123  }
124 
125  return -1;
126 }
127 
128 static int systick_suspend(struct st_device *dev)
129 {
130  stop_systick(); // SysTick停止
131 
132  return 0;
133 }
134 
135 static int systick_resume(struct st_device *dev)
136 {
137  start_systick(); // SysTickスタート
138 
139  return 0;
140 }
141 
142 const struct st_device cortexm_systick_device = {
144  .explan = "Cortex-M SysTick Driver",
145  .register_dev = systick_register,
146  .unregister_dev = systick_unregister,
147  .ioctl = systick_ioctl,
148  .suspend = systick_suspend,
149  .resume = systick_resume,
150 }; //!< SysTickデバイスドライバ
#define IOCMD_TIMER_GETSYSTIME
タイマの値を取得する(usec)
Definition: timer_ioctl.h:21
#define IOCMD_TIMER_SETFUNC
タイマの割り込みハンドラ処理を登録する
Definition: timer_ioctl.h:18
#define IOCMD_TIMER_STOP
タイマのカウントを停止する
Definition: timer_ioctl.h:20
カーネルタイマ
#define GSC_KERNEL_TIMER_INTERVAL_MSEC
$gsc カーネルタイマ割り込み間隔(ms)
Definition: timer.h:14
int tkprintf(const char *fmt,...)
非タスクコンテキスト実行用メッセージ出力
Definition: tkprintf.c:100
カーネル用機能限定printf
Cortex-M4
割り込みハンドラ
タスク制御
#define IOCMD_TIMER_GETTIME
タイマの値を取得する(msec)
Definition: timer_ioctl.h:17
#define IOCMD_TIMER_START
タイマのカウントを開始する
Definition: timer_ioctl.h:19
デバイスドライバAPI
デバイスドライバ構造体
Definition: device.h:25
char name[MAX_DEVNAMELRN]
デバイス名文字列
Definition: device.h:26
#define DEF_DEV_NAME_TIMER
標準タイマデバイス名
Definition: timer_ioctl.h:15
タイマドライバ ioctl 用マクロ定義