OSDN Git Service

LPC4330i存部のコードを追加。ビルドが通る。
[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 #if defined(TOPPERS_CHIP_LPC17XX) |  defined(TOPPERS_CHIP_LPC18XX) |  defined(TOPPERS_CHIP_LPC43XX)
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
170 #elif defined(TOPPERS_CHIP_LPC18XX) | defined(TOPPERS_CHIP_LPC43XX)
171
172 static const uint32_t sioreg_table[TNUM_PORT] = {
173     LPC_USART0_BASE
174 #if (TNUM_PORT >= 2)
175     ,LPC_UART1_BASE
176 #endif
177 #if (TNUM_PORT >= 3)
178     ,LPC_USART2_BASE
179 #endif
180 #if (TNUM_PORT >= 4)
181     ,LPC_USART3_BASE
182 #endif
183 };
184 #else
185 #error "You must define sioreg_table[]"
186 #endif
187
188 /**
189  * \ingroup SIOSUPPORT
190  * \brief シリアルポート・ペリフェラル書き込み関数
191  * \param addr UARTペリフェラルのベースアドレス。通常はTHRのアドレスである。
192  * \param offset ベースアドレスに対する、オフセット値。単位はバイト。
193  * \param val レジスタに書き込む値。
194  * \details
195  * ベースアドレスとオフセットを整数で受け取り、ペリフェラルレジスタに
196  * アクセスする。
197  */
198 Inline void
199 uart_write(uint32_t addr, uint32_t offset, uint8_t val)
200 {
201 #if defined(TOPPERS_CHIP_LPC17XX) |  defined(TOPPERS_CHIP_LPC18XX) |  defined(TOPPERS_CHIP_LPC43XX)
202     sil_wrb_mem((void *)(addr + offset),val);
203 #else
204 #error "You must define access method for your architecture"
205 #endif
206 }
207
208 /**
209  * \ingroup SIOSUPPORT
210  * \brief シリアルポート・ペリフェラル読み込み関数
211  * \param addr UARTペリフェラルのベースアドレス。通常はTHRのアドレスである。
212  * \param offset ベースアドレスに対する、オフセット値。単位はバイト。
213  * \return レジスタから読み込んだ値。
214  * \details
215  * ベースアドレスとオフセットを整数で受け取り、ペリフェラルレジスタに
216  * アクセスする。
217  */
218 Inline uint8_t
219 uart_read(uint32_t addr, uint32_t offset)
220 {
221 #if defined(TOPPERS_CHIP_LPC17XX) |  defined(TOPPERS_CHIP_LPC18XX) |  defined(TOPPERS_CHIP_LPC43XX)
222     return(sil_reb_mem((void *)(addr + offset)));
223 #else
224 #error "You must define access method for your architecture"
225 #endif
226 }
227
228 /**
229  * \ingroup TOPPERS_SIO
230  * \defgroup SIOAPI シリアル・サービス・タスク用API
231  * \details
232  * シリアル・サービス・タスクから呼び出される関数群。シリアル・サービス・タスクはこれらの
233  * 関数を使ってペリフェラルを制御する。詳細はporting.txtの8.3節を参照。
234  * \{
235  */
236
237
238 /**
239  * \brief シリアル・ポートが送信可能か調べる
240  * \param siopcb SIOを指し示すポート・コントロール・ブロックへのポインタ
241  * \return 送信可能であれば真、不能であれば偽を返す
242  * \details
243  * siopcbが指し示すシリアル・ペリフェラルを調べ、送信可能なら真を返す。
244  *
245  * 送信可能か否かの判断には、送信割り込みが許可されているかどうかも含まれる。イネーブルかつ送信レジスタに空きがあるなら
246  * 送信可能である。送信の可否に割り込み許可状態を含めるのは、送信割り込み禁止状態で送信コールバックを呼ぶことを防ぐため
247  * である。
248  *
249  * sio_putready()関数は sio_isr()関数から送信可能かどうかをチェックするために呼ばれる。もし、可能であれば sio_isr()は
250  * シリアル制御サービスの sio_irdy_snd()コールバック関数を呼び出してしまう。コールバック禁止状態でこの関数を呼ばない
251  * ようにするには、割り込み許可状態の確認が不可欠である。割り込み許可状態の設定に関しては sio_ena_cbr()関数と
252  * sio_dis_cbr()関数を参照のこと。
253  */
254 Inline bool_t  sio_putready(SIOPCB* siopcb)
255 {
256
257         uint32_t reg = siopcb->reg_base;        /* UARTのベースアドレスを取得 */
258
259                 /* THRが空ならば送信可能なので真を返す */
260         return (uart_read( reg, UART_LSR ) & LSR_TX_EMPTY);
261 }
262
263 /**
264  * \brief シリアル・ポートに受信データがあるか調べる
265  * \param siopcb SIOを指し示すポート・コントロール・ブロックへのポインタ
266  * \return 送信受信データがあれば真、なければ偽を返す
267  * \details
268  * siopcbが指し示すシリアル・ペリフェラルを調べ、受信データがあるなら真を返す。
269  *
270  * 受信可能か否かの判断には、受信割り込みが許可されているかどうかも含まれる。イネーブルかつ受信レジスタに受信データがあるなら
271  * 受信可能である。受信の可否に割り込み許可状態を含めるのは、受信割り込み禁止状態で受信コールバックを呼ぶことを防ぐため
272  * である。
273  *
274  * sio_getready()関数は sio_isr() 関数から受信可能かどうかをチェックするために呼ばれる。もし、可能であれば sio_isr()は
275  * シリアル制御サービスの sio_irdy_rcv()コールバック関数を呼び出してしまう。コールバック禁止状態でこの関数を呼ばない
276  * ようにするには、割り込み許可状態の確認が不可欠である。割り込み許可状態の設定に関しては sio_ena_cbr()関数と
277  * sio_dis_cbr()関数を参照のこと。
278  */
279 Inline bool_t sio_getready(SIOPCB* siopcb)
280 {
281         uint32_t reg = siopcb->reg_base;        /* UARTのベースアドレスを取得 */
282
283                 /* RBRがいっぱいならば受信可能なので真を返す */
284         return (uart_read( reg, UART_LSR ) & LSR_RX_DATA_READY);
285 }
286
287 /**
288  * \}
289  */
290
291 /**
292  * \ingroup TOPPERS_SIO
293  *  \defgroup SIOSUPPORT SIOサポート関数群
294  *  \{
295  */
296
297 /**
298  *  \brief ターゲットのシリアル初期化
299  *  \param siopid SIOのポートID
300  *  \details
301  *  siopidで指定されるターゲットのSIOペリフェラルを初期化する。初期化するのは、ストップビットやビット数といった
302  *  プロトコルのほか、ボーレートも含む。この館数は、target_initialize() 関数からも呼び出され、バナー出力用の
303  *  ポート初期化に使用される。
304  *
305  *  ボーレートの設定にはUARTへ供給されるクロック周波数の設定が必要であるが、これは全UARTで共通であると
306  *  仮定して決めうちしている。周波数はSIO_UART_CLOCKで指定する。単位はHzである。また、ボーレートは
307  *
308  *  SIO_BAUD_RATE_DEFAULTに設定されるが、上書きしたければSIOx_BAUD_RATEを宣言する。単位はBAUDである。
309  */
310 void target_uart_init(ID siopid)
311 {
312         uint32_t reg = sioreg_table[SIOPID2INDEX(siopid)];              /* 使用するUARTのベースアドレスを取得 */
313
314         /* UARTの無効化 */
315         uart_write( reg, UART_LCR, 0 );                         /* DLAB モードをいったんクリアする */
316         uart_write( reg, UART_FCR, 0 );                         /* FIFO クリア*/
317         uart_write( reg, UART_IER, 0 );                         /* 割り込みをディセーブルにする */
318
319         /* ボーレートの設定 */
320         uart_write( reg, UART_LCR, LCR_DLAB );  /* ディバイザ設定モードに移行 */
321
322         switch (siopid) {
323             case 1:
324 #if defined(SIO_BAUD_RATE_PORT1)
325                 uart_write( reg, UART_DLL, DLL((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT1/16)) );
326                 uart_write( reg, UART_DLM, DLM((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT1/16)) );
327 #else
328                 uart_write( reg, UART_DLL, DLL((SIO_UART_CLOCK/SIO_BAUD_RATE_DEFAULT/16)) );
329                 uart_write( reg, UART_DLM, DLM((SIO_UART_CLOCK/SIO_BAUD_RATE_DEFAULT/16)) );
330 #endif
331                 break;
332             case 2:
333 #if defined(SIO_BAUD_RATE_PORT2)
334                 uart_write( reg, UART_DLL, DLL((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT2/16)) );
335                 uart_write( reg, UART_DLM, DLM((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT2/16)) );
336 #else
337                 uart_write( reg, UART_DLL, DLL((SIO_UART_CLOCK/SIO_BAUD_RATE_DEFAULT/16)) );
338                 uart_write( reg, UART_DLM, DLM((SIO_UART_CLOCK/SIO_BAUD_RATE_DEFAULT/16)) );
339 #endif
340                 break;
341             case 3:
342 #if defined(SIO_BAUD_RATE_PORT3)
343                 uart_write( reg, UART_DLL, DLL((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT3/16)) );
344                 uart_write( reg, UART_DLM, DLM((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT3/16)) );
345 #else
346                 uart_write( reg, UART_DLL, DLL((SIO_UART_CLOCK/SIO_BAUD_RATE_DEFAULT/16)) );
347                 uart_write( reg, UART_DLM, DLM((SIO_UART_CLOCK/SIO_BAUD_RATE_DEFAULT/16)) );
348 #endif
349                 break;
350             case 4:
351 #if defined(SIO_BAUD_RATE_PORT4)
352                 uart_write( reg, UART_DLL, DLL((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT4/16)) );
353                 uart_write( reg, UART_DLM, DLM((SIO_UART_CLOCK/SIO_BAUD_RATE_PORT4/16)) );
354 #else
355                 uart_write( reg, UART_DLL, DLL((SIO_UART_CLOCK/SIO_BAUD_RATE_DEFAULT/16)) );
356                 uart_write( reg, UART_DLM, DLM((SIO_UART_CLOCK/SIO_BAUD_RATE_DEFAULT/16)) );
357 #endif
358                 break;
359         }
360
361         /* デバイザ設定モードから、通常モードに戻す */
362         uart_write( reg, UART_LCR, 0 );                         /* 通常モードに移行 */
363
364         /* プロトコルを設定。8bit, 1stop bit, parityなし */
365         uart_write( reg, UART_LCR, LCR_NP_8_1 );                /* 通常モードに移行 */
366
367 }
368
369 /**
370  *  \brief ターゲットのシリアル終了
371  *  \param siopid 終了するポートの番号
372  *  \details
373  *  指定したポートをディセーブルする。
374  *
375  */
376 void target_uart_term(ID siopid)
377 {
378         uint32_t reg = sioreg_table[SIOPID2INDEX(siopid)];
379
380         /* UARTの無効化 */
381         uart_write( reg, UART_IER, 0 );                         /* 割り込みをディセーブルにする */
382 }
383
384 /**
385  * \}
386  */
387
388 /**
389  * \ingroup SIOAPI
390  *  \brief SIO初期化
391  *  \param exinf ATTINI静的APIが渡す引数
392  *  \details
393  *  porting.txtにはtarget_serial.cfgにこの関数を初期化ルーチンとして
394  *  登録する静的APIを含めることになっている( ASP 1.3.2 )。
395  *
396  *  この関数はシリアル・ポート・サービス・タスク用に内部変数を初期化するだけであり、
397  *  デバイスの初期化は行っていない。デバイスの初期化はsio_opn_porが呼ばれたときに毎回行われる。
398  */
399 void sio_initialize(intptr_t exinf)
400 {
401         int i;
402
403         for (i = 0; i < TNUM_PORT; i++)
404         {
405                 siopcb_table[i].peripheral_index = i;
406                 siopcb_table[i].reg_base = sioreg_table[i];
407                 siopcb_table[i].exinf = 0;
408         }
409 }
410
411 /**
412  * \ingroup SIOAPI
413  * \brief シリアル・オープン
414  * \param siopid SIOを識別する番号。1から TNUM_PORTまでの整数
415  * \param exinf 拡張情報。コールバックを呼ぶときに引数として渡す
416  * \details
417  * シリアル・ペリフェラルを初期化する。ペリフェラルはプロトコル、スピードなどの
418  * 設定を終え、割り込み禁止状態で待機する。この関数に続いて sio_ena_cbrが
419  * 呼び出される。
420  *
421  * 引数extinfで渡される情報を処理する必要はない。この引数はそのまま
422  * sio_irdy_sndおよび sio_irdy_rcvコールバックに渡される。
423  *
424  * プロトコルは8bit, 1stopbit, parityなしに決めうちしていい。
425  */
426 SIOPCB *sio_opn_por(ID siopid, intptr_t exinf)
427 {
428         SIOPCB* siopcb;
429
430         if (siopid > TNUM_PORT) {
431                 return NULL;
432         }
433
434         siopcb = GET_SIOPCB(siopid);
435         siopcb->exinf = exinf;
436
437         target_uart_init(siopid);
438
439         return siopcb;
440 }
441
442 /**
443  * \ingroup SIOAPI
444  * \brief シリアルクローズ
445  * \param p_siopcb ポート識別用PCBへのポインタ
446  * \details
447  * ターゲットのポートを閉じる。ポートはディセーブルされ、割り込みは起きない。
448  */
449 void sio_cls_por(SIOPCB *p_siopcb)
450 {
451         target_uart_term(INDEX2SIOPID(p_siopcb->peripheral_index));
452 }
453
454 /**
455  * \ingroup SIOAPI
456  * \brief 割込みサービスルーチン
457  * \param exinf 拡張
458  * \details
459  * porting.txtの8.3節で養成されている割り込みサービスルーチン。
460  * このルーチンはextinfの情報を元にどの割り込みが発生したか自動判別
461  * している。
462  *
463  * extinfにどのような情報を与えるかは、明言されていないように思える。
464  * CORTEX-M3版ではポート番号(1から始まってTNUM_PORTまでの識別
465  * 番号)がtarget_erial.cfgの中でATTISRのextinf引数として与えられている。
466  */
467 void sio_isr(intptr_t exinf)
468 {
469         SIOPCB* siopcb = GET_SIOPCB(exinf);
470         int32_t reg = siopcb->reg_base;
471                 /* 送信コールバック可能でかつ送信可能なら、送信コールバックを呼ぶ  */
472         if (sio_putready(siopcb) && ( uart_read(reg, UART_IER) &  IER_TX)) {
473                 sio_irdy_snd(siopcb->exinf);
474         }
475                 /* 受信コールバック可能でかつ受信可能なら、受信コールバックを呼ぶ  */
476         if (sio_getready(siopcb) && ( uart_read(reg, UART_IER) &  IER_RX)) {
477                 sio_irdy_rcv(siopcb->exinf);
478         }
479 }
480
481 /**
482  * \ingroup SIOAPI
483  * \brief 1文字送信
484  * \param siopcb 送信するSIOポート
485  * \param c 送信する文字
486  * \return 送信に成功したら真、失敗したら偽
487  * \details
488  * シリアル制御タスクから呼び出されて1文字送信する関数。送信できた時には真を、できなかったときには偽を返す。
489  * 送信の成否は実際の出力ではなく、送信レジスタへ書き込めたかどうかで判断してよい。この場合、送信レジスタが
490  * いっぱいであれば、送信できなかったことになる
491  */
492 bool_t sio_snd_chr(SIOPCB *siopcb, char_t c)
493 {
494         uint32_t reg = siopcb->reg_base;        /* UARTのベースアドレスを取得 */
495
496         if (sio_putready(siopcb)) {
497                 uart_write( reg, UART_THR, c);
498
499                 return true;
500         }
501         else
502                 return false;
503 }
504
505 /**
506  * \ingroup SIOAPI
507  * \brief 1文字受信
508  * \param siopcb 受信するSIOポート
509  * \return 受信した文字 受信した文字を+0から+255までの正の値として返す。何も受信していないときには-1を返す。
510  * \details
511  * シリアル制御タスクから呼び出されて1文字受信する関数。何も受信していない時には、-1を返す。受信した文字は0から255までの正の数として返す。
512  */
513 int_t sio_rcv_chr(SIOPCB *siopcb)
514 {
515
516         int_t c = -1;
517         uint32_t reg = siopcb->reg_base;        /* UARTのベースアドレスを取得 */
518
519         if (sio_getready(siopcb)) {
520                 c = uart_read( reg, UART_RBR ) & 0xFF;
521         }
522
523         return c;
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_ena_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  *  \ingroup SIOAPI
555  *  \brief コールバックの禁止
556  *  \param siopcb コールバックを禁止するSIOポート
557  *  \param cbrtn SIO_RDY_SND あるいは SIO_RDY_RCV
558  *  \details
559  *  シリアル制御タスクのコールバック関数の呼び出しを禁止する関数。 cbrtn 引数を使って送信と受信のいずれの側で禁止するかを
560  *  指定する。
561  *
562  *  この関数はTOPPERS/ASPのシリアル制御タスクの中から呼び出される。コールバックの禁止にはペリフェラルの割り込み禁止機能を使う。
563  */
564 void sio_dis_cbr(SIOPCB *siopcb, uint_t cbrtn)
565 {
566         uint32_t reg = siopcb->reg_base;        /* UARTのベースアドレスを取得 */
567
568         switch (cbrtn) {
569         case SIO_RDY_SND:
570                 uart_write( reg, UART_IER, uart_read(reg, UART_IER) & ~IER_TX );        /* 送信割り込みを禁止 */
571                 break;
572         case SIO_RDY_RCV:
573                 uart_write( reg, UART_IER, uart_read(reg, UART_IER) & ~IER_RX );        /* 受信割り込みを禁止 */
574                 break;
575         default:
576                 break;
577         }
578 }
579
580 /**
581  *  \brief 1文字出力(ポーリングでの出力)
582  *  \ingroup SIOSUPPORT
583  *  \param c 出力する文字
584  *  \param siopid 出力するポートのID
585  *  \details
586  *  出力ポートにポーリングで一文字出力する。これはTOPPERS/ASPで割り込みが有効になる前に使用する関数である。
587  *  ポーリングを使うので通常タスクが使ってはいけない。
588  */
589 void sio_pol_snd_chr(char_t c, ID siopid)
590 {
591         uint32_t reg = sioreg_table[SIOPID2INDEX(siopid)];              /* 使用するUARTのベースアドレスを取得 */
592
593         uart_write( reg, UART_THR, c);
594
595         while ((uart_read( reg, UART_LSR ) & LSR_TX_EMPTY) == 0)
596                 ;
597 }
598