Advertisement
Guest User

Untitled

a guest
Apr 20th, 2020
505
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.70 KB | None | 0 0
  1.  
  2. <<ディスパッチャについて>>
  3.  下記のサンプルはSW1を押すとLED1が点灯し、
  4. SW2を押すとLED2が点灯するタスク2個のプログラムです。
  5. (これはあくまでも「ただのサンプル」です)
  6. ディスパッチャ(タイマ割り込み)が無ければ、もちろんtask1しか実行できません。
  7.  
  8. *実行権の切り替え
  9.  たとえば、タスク1を実行中にタイマ割込みが掛かると、
  10. CPUは割込み処理終了後に実行を再開するタスク1のアドレスを
  11. スタックメモリ1にプッシュ(退避)してから
  12. 下記の内容の割込み処理を順に実行します。
  13.  1)タスク1用の汎用レジスタZLとZH、フラグレジスタSREGの内容をスタックメモリ1に
  14.   プッシュ(退避)する
  15.  2)現在のスタックメモリ1用のスタックポインタを保存してあったスタックメモリ2用の
  16.   スタックポインタと交換する
  17.  3)タスク2用の汎用レジスタZLとZH、フラグレジスタSREGの内容をスタックメモリ2から
  18.   ポップ(復帰)する
  19.  4)RETI命令を実行して、中断していたタスク2の実行を再開する。
  20. 以上で、タスク1の実行を中断してタスク2へ移行します。
  21.  文章で説明すると分りにくいですが、下記サンプル1のリストのIRQ13処理を見れば
  22. すぐに分って貰えると思います。
  23. タスク2実行中にタイマ割込みが掛かると、同様にしてタスク2からタスク1に移行して、
  24. タスク1の続きを再開します。
  25.  
  26. *初期設定
  27.  タスク1の実行を開始する前に準備(初期設定)として、
  28. スタックメモリ2の内容を
  29. 「タスク2実行中に割り込みがかかって、タスク2からタスク1に切り替わり、
  30.  現在はタスク1を実行中」
  31. の状態にしておきます。
  32.  つまり、あらかじめスタックメモリ2にはタスク2の実行開始アドレスをセットし、
  33. 汎用レジスタZH、ZLとフラグレジスタSREGをセットしておきます。
  34. この3個のレジスタはタスク2の実行を開始すると、
  35. プログラム中で必要に応じてプログラマによって、
  36. あるいは命令の実行結果に従って設定されるので、初期設定時は任意の値でかまいません。
  37.  
  38. *保存レジスタ
  39.  各タスクで同じレジスタやメモリを別目的で使用していれば保存が必要です。
  40. どのレジスタやメモリをスタックに保存するかは、製作するプログラムの構造や
  41. 機能で決ります。
  42. したがってプログラム設計時に十分に検討する必要があります。
  43. 各タスクで、レジスタやメモリがどのような状態になっているのか、
  44. そしてどのような状態に変わるのか、変えたいのかで決めます。
  45.  本サンプル1ではZHレジスタを使用していないので、本来はZHを保存する必要がありません。
  46. しかしZレジスタペアとして使う事が多いので、私は常に保存しています。
  47. 私がこれまで作ってきたディスパッチャで最も保存数が多い場合でも
  48. ZL、ZH、YL、YHの4個でした。
  49.  フラグレジスタSREGの保存は必須でしょう。
  50.  
  51. *他にもいくつか注意すべきことがあります。
  52. ユーザー(ソフトウェア)ディスパッチ
  53.  たとえばポーリングループなどで条件成立をひたすら待っていると実行効率が下がるので、
  54.  条件が成立しなければ、実行権を返して他のタスクを実行します。
  55.  下記サンプル1のタイマ割込み処理に1命令追加すると、ユーザーディスパッチャになります。
  56. 実行を中断されたくない時のディスパッチ禁止
  57.  これはタイマ割込みが掛からないようにするだけです。
  58. リエントラントなサブルーチンの作り方
  59.  サブルーチン内で使用しているレジスタ、メモリはスタックに退避・復帰します。
  60. などなど。
  61.  
  62. *最後に
  63.  これで1個の20MHzーtiny2313が2個の10MHzーtiny2313に変わります
  64. ・・・なんて甘い話があるわけも無くw
  65. AVRはマルチタスクなんて全く考慮されていないので、色々な苦労が待ち構えています。
  66. 私はAVRで大きくて複雑なプログラムを書くことは無いので、
  67. ディスパッチャを使う頻度はAVRのプログラミングの5回に1回程度の割合です。
  68. もちろん他のCPUでも応用できます。
  69. タスク分けの具体例はたとえばアナログデータ収集装置なら、
  70.  1)AD変換とバッファリング
  71.  2)操作パネルのSWやロータリエンコ-ダと液晶表示器の処理
  72.  3)PCとの通信によるファイル転送
  73. の3タスクなど。
  74.  
  75. *サンプル tiny2313用ディスパッチャ プログラムリスト(コード生成部のみ)
  76. ;***** tiny2313 vectors ***************
  77. C:000000 c020 rjmp RESET ;00 RESET
  78. C:000001 9518 reti ;01 INT0
  79. C:000002 9518 reti ;02 INT1
  80. C:000003 9518 reti ;03 timer1 Capt
  81. C:000004 9518 reti ;04 CompA
  82. C:000005 9518 reti ;05 OVF1
  83. C:000006 9518 reti ;06 timer0 OVF0
  84. C:000007 9518 reti ;07 USART RX
  85. C:000008 9518 reti ;08 UDRE
  86. C:000009 9518 reti ;09 TX
  87. C:00000a 9518 reti ;10 ANA_COMP
  88. C:00000b 9518 reti ;11 PCINT0
  89. C:00000c 9518 reti ;12 timer1 CompB
  90. C:00000d c007 rjmp IRQ13 ;13 timer0 CompA
  91. C:00000e 9518 reti ;14 CompB
  92. C:00000f 9518 reti ;15 I2C Start Condition
  93. C:000010 9518 reti ;16 Over Flow
  94. C:000011 9518 reti ;17 EEPROM EEw_Rdy
  95. C:000012 9518 reti ;18 WDT
  96. C:000013 9518 reti ;19 PCINT1
  97. C:000014 9518 reti ;20 PCINT2
  98. ;
  99. ;===== timer0 for dispatch ============
  100. ; CompA:interval 1mS
  101. ; execute time about 1uS at 20MHz system clock
  102. IRQ13:
  103. C:000015 93ef push ZL ;save ZL,ZH & SREG to currrent stack
  104. C:000016 93ff push ZH
  105. C:000017 b7ef in ZL,SREG
  106. C:000018 93ef push ZL
  107. ;
  108. C:000019 2de1 mov ZL,sv_SPL ;exchange SP task1 <--> task2
  109. C:00001a b61d in sv_SPL,SPL
  110. C:00001b bfed out SPL,ZL
  111. ;
  112. C:00001c 91ef pop ZL ;restore ZL,ZH & SREG from next stack
  113. C:00001d bfef out SREG,ZL
  114. C:00001e 91ff pop ZH
  115. C:00001f 91ef pop ZL
  116. C:000020 9518 reti ;exec. next task
  117. ;
  118. ;***** system setup *******************
  119. RESET:
  120. ;----- Port_B
  121. C:000021 efef ldi ZL,0b11111111 ;b0/1:output_Hi for LED1/LED2
  122. C:000022 bbe8 out PortB,ZL ;b2/3:input_PullUp for SW1/SW2
  123. C:000023 e8e3 ldi ZL,0b10000011 ;bit7:output for check
  124. C:000024 bbe7 out DDRB,ZL
  125. ;
  126. ;----- stack2 for task dispatch
  127. C:000025 e8ef ldi ZL,stack2 ;set stack2($8F) to SPL
  128. C:000026 bfed out SPL,ZL
  129. C:000027 e4e1 ldi ZL,LOW(task2) ;push task2 strat adrs for PCL
  130. C:000028 93ef push ZL
  131. C:000029 e0e0 ldi ZL,HIGH(task2) ; PCH
  132. C:00002a 93ef push ZL
  133. C:00002b 93ef push ZL ; dumy ZL
  134. C:00002c 93ef push ZL ; ZH
  135. C:00002d 93ef push ZL ; SREG
  136. C:00002e b61d in sv_SPL,SPL ;save task2 SPL
  137. ;
  138. C:00002f e7ef ldi ZL,stack1 ;set stack1($7F) to SPL
  139. C:000030 bfed out SPL,ZL
  140. ;
  141. ;----- timer0 for 1mS interval
  142. C:000031 e0e2 ldi ZL,0b00000010 ;set simple-CTC mode
  143. C:000032 bfe0 out TCCR0A,ZL
  144. C:000033 e0e4 ldi ZL,0b00000100 ;prescale system clock by 256
  145. C:000034 bfe3 out TCCR0B,ZL
  146. C:000035 e4ed ldi ZL,77 ;count up for 1mS interval
  147. C:000036 bfe6 out OCR0A,ZL
  148. C:000037 27ee clr ZL ;clear TCNT=0
  149. C:000038 bfe2 out TCNT0,ZL
  150. C:000039 e0e1 ldi ZL,0b00000001 ;enable intrpt by comp_A
  151. C:00003a bfe9 out TIMSK,ZL
  152. ;
  153. C:00003b 9478 sei ;intrpt enable
  154. ;
  155. ;***** task1 **************************
  156. task1:
  157. C:00003c 99b2 sbic PinB,_SW1 ;SW1 pushed ?
  158. C:00003d 9ac0 sbi PortB,_LED1 ;No, then LED1 OFF
  159. C:00003e 9bb2 sbis PinB,_SW1 ;SW1 pushed ?
  160. C:00003f 98c0 cbi PortB,_LED1 ;Yes, then LED1 ON
  161. C:000040 cffb rjmp task1
  162. ;
  163. ;***** task2 **************************
  164. task2:
  165. C:000041 99b3 sbic PinB,_SW2 ;SW2 pushed ?
  166. C:000042 9ac1 sbi PortB,_LED2 ;No, then LED2 OFF
  167. C:000043 9bb3 sbis PinB,_SW2 ;SW2 pushed ?
  168. C:000044 98c1 cbi PortB,_LED2 ;Yes, then LED2 ON
  169. C:000045 cffb rjmp task2
  170. ;
  171.  
  172. HEXファイル
  173. :020000020000FC
  174. :1000000020C0189518951895189518951895189555
  175. :100010001895189518951895189507C0189518955E
  176. :1000200018951895189518951895EF93FF93EFB7B5
  177. :10003000EF93E12D1DB6EDBFEF91EFBFFF91EF9173
  178. :100040001895EFEFE8BBE3E8E7BBEFE8EDBFE1E4CD
  179. :10005000EF93E0E0EF93EF93EF93EF931DB6EFE7AD
  180. :10006000EDBFE2E0E0BFE4E0E3BFEDE4E6BFEE2792
  181. :10007000E2BFE1E0E9BF7894B299C09AB29BC09820
  182. :0C008000FBCFB399C19AB39BC198FBCF92
  183. :00000001FF
  184.  
  185. 少し具体的ななサンプルですが(といってもLチカですが)
  186. https://pastebin.com/hZ4EiF7m
  187.  通常時はスイッチ別にタスク8個で、ゲーム時はシングルタスクで動かしています。
  188. ソフトウェア(ループ)ディレイはリエントラントで、各タスクで共通して使っています。
  189. ユーザーディスパッチャは使用していません。
  190. プログラムリストは省略します。興味ある方は逆アセンブルしてください。
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement