OSDN Git Service

b50ba581ad6eebcfe5e6cfa8f0fb31026658269c
[toppersasp4lpc/asp.git] / asp / pdic / uart / uart.c
1 /*
2  *  TOPPERS/ASP Kernel
3  *      Toyohashi Open Platform for Embedded Real-Time Systems/
4  *      Advanced Standard Profile Kernel
5  * 
6  *  Copyright (C) 2007 by Embedded and Real-Time Systems Laboratory
7  *              Graduate School of Information Science, Nagoya Univ., JAPAN
8  *  Copyright (C) 2010 by TOPPERS/ASP for LPC project
9  *              http://sourceforge.jp/projects/toppersasp4lpc/
10  *
11  * 
12  *  上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
13  *  ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
14  *  変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
15  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
16  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
17  *      スコード中に含まれていること.
18  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
19  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
20  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
21  *      の無保証規定を掲載すること.
22  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
23  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
24  *      と.
25  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
26  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
27  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
28  *        報告すること.
29  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
30  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
31  *      また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
32  *      由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
33  *      免責すること.
34  * 
35  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
36  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
37  *  に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
38  *  アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
39  *  の責任を負わない.
40  * 
41  */
42 /**
43  * \file uart.c
44  * \ingroup TOPPERS_SIO
45  * \brief ターゲット依存のシリアル・ペリフェラル制御ルーチン群
46  * \details
47  *  ターゲット依存のシリアル・ペリフェラル制御ルーチン群。TOPPERS/ASPのシリアル
48  *  ・タスクの下請けとして働く。詳細に関してはporting.txtを参照のこと。
49  *
50  */
51
52 /*
53  * シリアルドライバ(UART汎用)
54  */
55
56 #include <kernel.h>
57 #include <sil.h>
58 #include "uart.h"
59 #include "target_syssvc.h"
60
61 /*
62  * レジスタ設定値
63  */
64 /**
65  * \brief SIOPCBのインデックスからポートID番号への変換
66  * \details
67  * TOPPERS/ASPのSIOポートID番号は1オリジンだが、 siopcb_table[]は
68  * 0オリジンである。そのため、変換関数を使って与えられたインデックス番号から
69  * ポートID番号を作り出す。
70  *
71  */
72 #define INDEX2SIOPID(x) ((x) + 1)
73 /**
74  * \brief ポート番号からSIOPCBのインデックスへの変換
75  * \details
76  * TOPPERS/ASPのSIOポートID番号は1オリジンだが、 siopcb_table[]は
77  * 0オリジンである。そのため、変換関数を使って与えられたポートID番号から
78  * PCBを取得するためのインデックスを作り出す。
79  */
80 #define SIOPID2INDEX(x) ((x) - 1)
81 /**
82  * \brief ポートID番号からSIOPCBを取得する
83  * \details
84  * ポートID番号を元に、SIOPCBへのポインタを取得する。
85  */
86 #define GET_SIOPCB(x)   (&siopcb_table[SIOPID2INDEX(x)])
87
88
89 /**
90  * \brief ペリフェラル・レジスタの間隔
91  * \details
92  * ペリフェラルレジスタが何バイトごとに現れるかを記述する。この
93  * 記述はチップごとに変わる。
94  */
95 #ifdef TOPPERS_CHIP_LPC17XX
96 #define UART_BOUNDARY 4
97 #else
98 #error "You must define UART_BOUNDARY for your architecture"
99 #endif
100 /**
101  * \brief 8250, 16450, 16550各レジスタのアドレス・オフセット。
102  * \details
103  * UART_RHRを基点とする。
104  * システムごとに異なるのでUART_BOUNDARYによってレジスタの配置境界を指定する。
105  * たとえばすべてのレジスタが8ビット境界で配置されているなら、UART_BOUNDARYは1,
106  * 16bit境界なら2, 32ビット境界なら4を指定する。
107  * UART_BOUNDARYはsys_config.hで定義する。
108  */
109
110 #define UART_RBR   (0x00 * UART_BOUNDARY)   /*  受信バッファレジスタ  */
111 #define UART_THR   (0x00 * UART_BOUNDARY)   /*  送信データ・ホールド・レジスタ */
112 #define UART_DLL   (0x00 * UART_BOUNDARY)   /*  分周レジスタ下位バイト       */
113 #define UART_IER   (0x01 * UART_BOUNDARY)   /*  割込みイネーブルレジスタ       */
114 #define UART_DLM   (0x01 * UART_BOUNDARY)   /*  分周レジスタ上位バイト       */
115 #define UART_IIR   (0x02 * UART_BOUNDARY)   /*  割込み識別レジスタ  */
116 #define UART_FCR   (0x02 * UART_BOUNDARY)   /*  FIFO制御レジスタ  */
117 #define UART_LCR   (0x03 * UART_BOUNDARY)   /*  ライン制御レジスタ */
118 #define UART_MCR   (0x04 * UART_BOUNDARY)   /*  モデム制御レジスタ */
119 #define UART_LSR   (0x05 * UART_BOUNDARY)   /*  ライン・ステータス・レジスタ */
120 #define UART_MSR   (0x06 * UART_BOUNDARY)   /*  モデム・ステータス・レジスタ */
121 #define UART_SCR   (0x07 * UART_BOUNDARY)   /*  スクラッチ・パッド・レジスタ */
122 #define UART_GCTL  (0x09 * UART_BOUNDARY)         /*  Blackfinのみ。グローバル制御レジスタ */
123
124 #define ISR_TX            0x02       /* 送信割り込み発生 */
125 #define IER_TX            0x02       /* 送信割り込み許可 */
126 #define ISR_RX            0x01       /* 受信割り込み発生 */
127 #define IER_RX            0x01       /* 受信割り込み許可 */
128
129 #define LCR_DLAB                          0x80       /* Divisor Enable */
130 #define LCR_NP_8_1        0x03       /* 8bit,1stop,Noparity,No break */
131 #define FCR_FIFO_DISABLE  0x00
132
133 #define LSR_RX_DATA_READY 0x01
134 #define LSR_TX_EMPTY      0x20
135
136 #define MCR_INT_ENABLE    0x08
137
138 /* ディバイザ計算マクロ */
139 #define DLM(divisor) (divisor/256)
140 #define DLL(divisor) (divisor%256)
141
142
143 /**
144  * \brief シリアルI/Oポート管理ブロックエリア
145  */
146 SIOPCB siopcb_table[TNUM_PORT];
147
148 /**
149  * \brief 各シリアル・ペリフェラルのレジスタのベースアドレス。
150  * \details
151  * この変数は初期化関数 sio_initialize()の中で参照され、
152  * レジスタアドレスは siopcb_table[]のしかるべきメンバー変数に
153  * 代入される。
154  */
155
156 #ifdef TOPPERS_CHIP_LPC17XX
157 static const uint32_t sioreg_table[TNUM_PORT] = {
158         LPC_UART0_BASE
159 #if (TNUM_PORT >= 2)
160         ,LPC_UART1_BASE
161 #endif
162 #if (TNUM_PORT >= 3)
163         ,LPC_UART2_BASE
164 #endif
165 #if (TNUM_PORT >= 4)
166         ,LPC_UART3_BASE
167 #endif
168 };
169 #else
170 #error "You must define sioreg_table[]"
171 #endif
172
173 /**
174  * \ingroup SIOSUPPORT
175  * \brief シリアルポート・ペリフェラル書き込み関数
176  * \param addr UARTペリフェラルのベースアドレス。通常はTHRのアドレスである。
177  * \param offset ベースアドレスに対する、オフセット値。単位はバイト。
178  * \param val レジスタに書き込む値。
179  * \details
180  * ベースアドレスとオフセットを整数で受け取り、ペリフェラルレジスタに
181  * アクセスする。
182  */
183 Inline void
184 uart_write(uint32_t addr, uint32_t offset, uint8_t val)
185 {
186 #ifdef TOPPERS_CHIP_LPC17XX
187     sil_wrb_mem((void *)(addr + offset),val);
188 #else
189 #error "You must define access method for your architecture"
190 #endif
191 }
192
193 /**
194  * \ingroup SIOSUPPORT
195  * \brief シリアルポート・ペリフェラル読み込み関数
196  * \param addr UARTペリフェラルのベースアドレス。通常はTHRのアドレスである。
197  * \param offset ベースアドレスに対する、オフセット値。単位はバイト。
198  * \return レジスタから読み込んだ値。
199  * \details
200  * ベースアドレスとオフセットを整数で受け取り、ペリフェラルレジスタに
201  * アクセスする。
202  */
203 Inline uint8_t
204 uart_read(uint32_t addr, uint32_t offset)
205 {
206 #ifdef TOPPERS_CHIP_LPC17XX
207     return(sil_reb_mem((void *)(addr + offset)));
208 #else
209 #error "You must define access method for your architecture"
210 #endif
211 }
212
213 /**
214  * \ingroup TOPPERS_SIO
215  * \defgroup SIOAPI シリアル・サービス・タスク用API
216  * \details
217  * シリアル・サービス・タスクから呼び出される関数群。シリアル・サービス・タスクはこれらの
218  * 関数を使ってペリフェラルを制御する。詳細はporting.txtの8.3節を参照。
219  * \{
220  */
221
222
223 /**
224  * \brief シリアル・ポートが送信可能か調べる
225  * \param siopcb SIOを指し示すポート・コントロール・ブロックへのポインタ
226  * \return 送信可能であれば真、不能であれば偽を返す
227  * \details
228  * siopcbが指し示すシリアル・ペリフェラルを調べ、送信可能なら真を返す。
229  *
230  * 送信可能か否かの判断には、送信割り込みが許可されているかどうかも含まれる。イネーブルかつ送信レジスタに空きがあるなら
231  * 送信可能である。送信の可否に割り込み許可状態を含めるのは、送信割り込み禁止状態で送信コールバックを呼ぶことを防ぐため
232  * である。
233  *
234  * sio_putready()関数は sio_isr()関数から送信可能かどうかをチェックするために呼ばれる。もし、可能であれば sio_isr()は
235  * シリアル制御サービスの sio_irdy_snd()コールバック関数を呼び出してしまう。コールバック禁止状態でこの関数を呼ばない
236  * ようにするには、割り込み許可状態の確認が不可欠である。割り込み許可状態の設定に関しては sio_ena_cbr()関数と
237  * sio_dis_cbr()関数を参照のこと。
238  */
239 Inline bool_t  sio_putready(SIOPCB* siopcb)
240 {
241
242         uint32_t reg = siopcb->reg_base;        /* UARTのベースアドレスを取得 */
243
244                 /* THRが空ならば送信可能なので真を返す */
245         return (uart_read( reg, UART_LSR ) & LSR_TX_EMPTY);
246 }
247
248 /**
249  * \brief シリアル・ポートに受信データがあるか調べる
250  * \param siopcb SIOを指し示すポート・コントロール・ブロックへのポインタ
251  * \return 送信受信データがあれば真、なければ偽を返す
252  * \details
253  * siopcbが指し示すシリアル・ペリフェラルを調べ、受信データがあるなら真を返す。
254  *
255  * 受信可能か否かの判断には、受信割り込みが許可されているかどうかも含まれる。イネーブルかつ受信レジスタに受信データがあるなら
256  * 受信可能である。受信の可否に割り込み許可状態を含めるのは、受信割り込み禁止状態で受信コールバックを呼ぶことを防ぐため
257  * である。
258  *
259  * sio_getready()関数は sio_isr() 関数から受信可能かどうかをチェックするために呼ばれる。もし、可能であれば sio_isr()は
260  * シリアル制御サービスの sio_irdy_rcv()コールバック関数を呼び出してしまう。コールバック禁止状態でこの関数を呼ばない
261  * ようにするには、割り込み許可状態の確認が不可欠である。割り込み許可状態の設定に関しては sio_ena_cbr()関数と
262  * sio_dis_cbr()関数を参照のこと。
263  */
264 Inline bool_t sio_getready(SIOPCB* siopcb)
265 {
266         uint32_t reg = siopcb->reg_base;        /* UARTのベースアドレスを取得 */
267
268                 /* RBRがいっぱいならば受信可能なので真を返す */
269         return (uart_read( reg, UART_LSR ) & LSR_RX_DATA_READY);
270 }
271
272 /**
273  * \}
274  */
275
276 /**
277  * \ingroup TOPPERS_SIO
278  *  \defgroup SIOSUPPORT SIOサポート関数群
279  *  \{
280  */
281
282 /**
283  *  \brief ターゲットのシリアル初期化
284  *  \param siopid SIOのポートID
285  *  \details
286  *  siopidで指定されるターゲットのSIOペリフェラルを初期化する。初期化するのは、ストップビットやビット数といった
287  *  プロトコルのほか、ボーレートも含む。この館数は、target_initialize() 関数からも呼び出され、バナー出力用の
288  *  ポート初期化に使用される。
289  *
290  *  ボーレートの設定にはUARTへ供給されるクロック周波数の設定が必要であるが、これは全UARTで共通であると
291  *  仮定して決めうちしている。周波数はSIO_UART_CLOCKで指定する。単位はHzである。また、ボーレートは
292  *
293  *  SIO_BAUD_RATE_DEFAULTに設定されるが、上書きしたければSIOx_BAUD_RATEを宣言する。単位はBAUDである。
294  */
295 void target_uart_init(ID siopid)
296 {
297         uint32_t reg = sioreg_table[SIOPID2INDEX(siopid)];              /* 使用するUARTのベースアドレスを取得 */
298
299         /* UARTの無効化 */
300         uart_write( reg, UART_LCR, 0 );                         /* DLAB モードをいったんクリアする */
301         uart_write( reg, UART_FCR, 0 );                         /* FIFO クリア*/
302         uart_write( reg, UART_IER, 0 );                         /* 割り込みをディセーブルにする */
303
304         /* ボーレートの設定 */
305         uart_write( reg, UART_LCR, LCR_DLAB );  /* ディバイザ設定モードに移行 */
306
307         switch (siopid) {
308             case 1:
309 #if defined(SIO_BAUD_RATE_PORT1)
310                 uart_write( reg, UART_DLL, DLL((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT1/16)) );
311                 uart_write( reg, UART_DLM, DLM((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT1/16)) );
312 #endif
313                 break;
314             case 2:
315 #if defined(SIO_BAUD_RATE_PORT2)
316                 uart_write( reg, UART_DLL, DLL((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT2/16)) );
317                 uart_write( reg, UART_DLM, DLM((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT2/16)) );
318 #endif
319                 break;
320             case 3:
321 #if defined(SIO_BAUD_RATE_PORT3)
322                 uart_write( reg, UART_DLL, DLL((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT3/16)) );
323                 uart_write( reg, UART_DLM, DLM((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT3/16)) );
324 #endif
325                 break;
326             case 4:
327 #if defined(SIO_BAUD_RATE_PORT4)
328                 uart_write( reg, UART_DLL, DLL((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT4/16)) );
329                 uart_write( reg, UART_DLM, DLM((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT4/16)) );
330 #endif
331                 break;
332         }
333
334         /* デバイザ設定モードから、通常モードに戻す */
335         uart_write( reg, UART_LCR, 0 );                         /* 通常モードに移行 */
336
337         /* プロトコルを設定。8bit, 1stop bit, parityなし */
338         uart_write( reg, UART_LCR, LCR_NP_8_1 );                /* 通常モードに移行 */
339
340 }
341
342 /**
343  *  \brief ターゲットのシリアル終了
344  *  \param siopid 終了するポートの番号
345  *  \details
346  *  指定したポートをディセーブルする。
347  *
348  */
349 void target_uart_term(ID siopid)
350 {
351         uint32_t reg = sioreg_table[SIOPID2INDEX(siopid)];
352
353         /* UARTの無効化 */
354         uart_write( reg, UART_IER, 0 );                         /* 割り込みをディセーブルにする */
355 }
356
357 /**
358  * \}
359  */
360
361 /**
362  * \ingroup SIOAPI
363  *  \brief SIO初期化
364  *  \param exinf ATTINI静的APIが渡す引数
365  *  \details
366  *  porting.txtにはtarget_serial.cfgにこの関数を初期化ルーチンとして
367  *  登録する静的APIを含めることになっている( ASP 1.3.2 )。
368  *
369  *  この関数はシリアル・ポート・サービス・タスク用に内部変数を初期化するだけであり、
370  *  デバイスの初期化は行っていない。デバイスの初期化はsio_opn_porが呼ばれたときに毎回行われる。
371  */
372 void sio_initialize(intptr_t exinf)
373 {
374         int i;
375
376         for (i = 0; i < TNUM_PORT; i++)
377         {
378                 siopcb_table[i].peripheral_index = i;
379                 siopcb_table[i].reg_base = sioreg_table[i];
380                 siopcb_table[i].exinf = 0;
381         }
382 }
383
384 /**
385  * \ingroup SIOAPI
386  * \brief シリアル・オープン
387  * \param siopid SIOを識別する番号。1から TNUM_PORTまでの整数
388  * \param exinf 拡張情報。コールバックを呼ぶときに引数として渡す
389  * \details
390  * シリアル・ペリフェラルを初期化する。ペリフェラルはプロトコル、スピードなどの
391  * 設定を終え、割り込み禁止状態で待機する。この関数に続いて sio_ena_cbrが
392  * 呼び出される。
393  *
394  * 引数extinfで渡される情報を処理する必要はない。この引数はそのまま
395  * sio_irdy_sndおよび sio_irdy_rcvコールバックに渡される。
396  *
397  * プロトコルは8bit, 1stopbit, parityなしに決めうちしていい。
398  */
399 SIOPCB *sio_opn_por(ID siopid, intptr_t exinf)
400 {
401         SIOPCB* siopcb;
402
403         if (siopid > TNUM_PORT) {
404                 return NULL;
405         }
406
407         siopcb = GET_SIOPCB(siopid);
408         siopcb->exinf = exinf;
409
410         target_uart_init(siopid);
411
412         return siopcb;
413 }
414
415 /**
416  * \ingroup SIOAPI
417  * \brief シリアルクローズ
418  * \param p_siopcb ポート識別用PCBへのポインタ
419  * \details
420  * ターゲットのポートを閉じる。ポートはディセーブルされ、割り込みは起きない。
421  */
422 void sio_cls_por(SIOPCB *p_siopcb)
423 {
424         target_uart_term(INDEX2SIOPID(p_siopcb->peripheral_index));
425 }
426
427 /**
428  * \ingroup SIOAPI
429  * \brief 割込みサービスルーチン
430  * \param exinf 拡張
431  * \details
432  * porting.txtの8.3節で養成されている割り込みサービスルーチン。
433  * このルーチンはextinfの情報を元にどの割り込みが発生したか自動判別
434  * している。
435  *
436  * extinfにどのような情報を与えるかは、明言されていないように思える。
437  * CORTEX-M3版ではポート番号(1から始まってTNUM_PORTまでの識別
438  * 番号)がtarget_erial.cfgの中でATTISRのextinf引数として与えられている。
439  */
440 void sio_isr(intptr_t exinf)
441 {
442         SIOPCB* siopcb = GET_SIOPCB(exinf);
443         int32_t reg = siopcb->reg_base;
444                 /* 送信コールバック可能でかつ送信可能なら、送信コールバックを呼ぶ  */
445         if (sio_putready(siopcb) && ( uart_read(reg, UART_IER) &  IER_TX)) {
446                 sio_irdy_snd(siopcb->exinf);
447         }
448                 /* 受信コールバック可能でかつ受信可能なら、受信コールバックを呼ぶ  */
449         if (sio_getready(siopcb) && ( uart_read(reg, UART_IER) &  IER_RX)) {
450                 sio_irdy_rcv(siopcb->exinf);
451         }
452 }
453
454 /**
455  * \ingroup SIOAPI
456  * \brief 1文字送信
457  * \param siopcb 送信するSIOポート
458  * \param c 送信する文字
459  * \return 送信に成功したら真、失敗したら偽
460  * \details
461  * シリアル制御タスクから呼び出されて1文字送信する関数。送信できた時には真を、できなかったときには偽を返す。
462  * 送信の成否は実際の出力ではなく、送信レジスタへ書き込めたかどうかで判断してよい。この場合、送信レジスタが
463  * いっぱいであれば、送信できなかったことになる
464  */
465 bool_t sio_snd_chr(SIOPCB *siopcb, char_t c)
466 {
467         uint32_t reg = siopcb->reg_base;        /* UARTのベースアドレスを取得 */
468
469         if (sio_putready(siopcb)) {
470                 uart_write( reg, UART_THR, c);
471
472                 return true;
473         }
474         else
475                 return false;
476 }
477
478 /**
479  * \ingroup SIOAPI
480  * \brief 1文字受信
481  * \param siopcb 受信するSIOポート
482  * \return 受信した文字 受信した文字を+0から+255までの正の値として返す。何も受信していないときには-1を返す。
483  * \details
484  * シリアル制御タスクから呼び出されて1文字受信する関数。何も受信していない時には、-1を返す。受信した文字は0から255までの正の数として返す。
485  */
486 int_t sio_rcv_chr(SIOPCB *siopcb)
487 {
488
489         int_t c = -1;
490         uint32_t reg = siopcb->reg_base;        /* UARTのベースアドレスを取得 */
491
492         if (sio_getready(siopcb)) {
493                 c = uart_read( reg, UART_RBR ) & 0xFF;
494         }
495
496         return c;
497 }
498
499 /**
500  *  \ingroup SIOAPI
501  *  \brief コールバックの許可
502  *  \param siopcb コールバックを許可するSIOポート
503  *  \param cbrtn SIO_RDY_SND あるいは SIO_RDY_RCV
504  *  \details
505  *  シリアル制御タスクのコールバック関数の呼び出しを許可する関数。 cbrtn 引数を使って送信と受信のいずれの側で許可するかを
506  *  指定する。
507  *
508  *  この関数はTOPPERS/ASPのシリアル制御タスクの中から呼び出される。コールバックの許可にはペリフェラルの割り込み許可機能を使う。
509  */
510 void sio_ena_cbr(SIOPCB *siopcb, uint_t cbrtn)
511 {
512         uint32_t reg = siopcb->reg_base;        /* UARTのベースアドレスを取得 */
513
514         switch (cbrtn) {
515         case SIO_RDY_SND:
516                 uart_write( reg, UART_IER, uart_read(reg, UART_IER) | IER_TX ); /* 送信割り込みを許可 */
517                 break;
518         case SIO_RDY_RCV:
519                 uart_write( reg, UART_IER, uart_read(reg, UART_IER) | IER_RX ); /* 受信割り込みを許可 */
520                 break;
521         default:
522                 break;
523         }
524 }
525
526 /**
527  *  \ingroup SIOAPI
528  *  \brief コールバックの禁止
529  *  \param siopcb コールバックを禁止するSIOポート
530  *  \param cbrtn SIO_RDY_SND あるいは SIO_RDY_RCV
531  *  \details
532  *  シリアル制御タスクのコールバック関数の呼び出しを禁止する関数。 cbrtn 引数を使って送信と受信のいずれの側で禁止するかを
533  *  指定する。
534  *
535  *  この関数はTOPPERS/ASPのシリアル制御タスクの中から呼び出される。コールバックの禁止にはペリフェラルの割り込み禁止機能を使う。
536  */
537 void sio_dis_cbr(SIOPCB *siopcb, uint_t cbrtn)
538 {
539         uint32_t reg = siopcb->reg_base;        /* UARTのベースアドレスを取得 */
540
541         switch (cbrtn) {
542         case SIO_RDY_SND:
543                 uart_write( reg, UART_IER, uart_read(reg, UART_IER) & ~IER_TX );        /* 送信割り込みを禁止 */
544                 break;
545         case SIO_RDY_RCV:
546                 uart_write( reg, UART_IER, uart_read(reg, UART_IER) & ~IER_RX );        /* 受信割り込みを禁止 */
547                 break;
548         default:
549                 break;
550         }
551 }
552
553 /**
554  *  \brief 1文字出力(ポーリングでの出力)
555  *  \ingroup SIOSUPPORT
556  *  \param c 出力する文字
557  *  \param siopid 出力するポートのID
558  *  \details
559  *  出力ポートにポーリングで一文字出力する。これはTOPPERS/ASPで割り込みが有効になる前に使用する関数である。
560  *  ポーリングを使うので通常タスクが使ってはいけない。
561  */
562 void sio_pol_snd_chr(char_t c, ID siopid)
563 {
564         uint32_t reg = sioreg_table[SIOPID2INDEX(siopid)];              /* 使用するUARTのベースアドレスを取得 */
565
566         uart_write( reg, UART_THR, c);
567
568         while ((uart_read( reg, UART_LSR ) & LSR_TX_EMPTY) == 0)
569                 ;
570 }
571