source: uKadecot/trunk/ssp/pdic/rx600/rx630_uart.c@ 108

Last change on this file since 108 was 108, checked in by coas-nagasima, 9 years ago

MIMEプロパティの変更

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-chdr; charset=SHIFT_JIS
File size: 11.6 KB
Line 
1/*
2 * TOPPERS/SSP Kernel
3 * Smallest Set Profile Kernel
4 *
5 * Copyright (C) 2008-2010 by Witz Corporation, JAPAN
6 * Copyright (C) 2013 by Mitsuhiro Matsuura
7 *
8 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
9 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
10 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
11 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
12 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
13 * スコード中に含まれていること.
14 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
15 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
16 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
17 * の無保証規定を掲載すること.
18 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
19 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
20 * と.
21 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
22 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
23 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
24 * 報告すること.
25 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
26 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
27 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
28 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
29 * 免責すること.
30 *
31 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
32 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
33 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
34 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
35 * の責任を負わない.
36 *
37 */
38
39
40/*
41 * UART用 簡易SIOドライバ
42 */
43
44#include <sil.h>
45#include <kernel.h>
46#include <t_syslog.h>
47#include "target_syssvc.h"
48#include "rx630_uart.h"
49
50/* シリアルモードレジスタ(SMR) */
51#define CKS UINT_C(0x03)
52#define STOP UINT_C(0x08)
53#define PM UINT_C(0x10)
54#define PE UINT_C(0x20)
55#define CHR UINT_C(0x40)
56#define CM UINT_C(0x80)
57#define ASYNC_7BIT UINT_C(0x00)
58#define ASYNC_8BIT UINT_C(0x40)
59
60/* シリアルコントロールレジスタ(SCR) */
61#define CKE UINT_C(0x03)
62#define TEIE UINT_C(0x04)
63#define RE UINT_C(0x10)
64#define TE UINT_C(0x20)
65#define RIE UINT_C(0x40)
66#define TIE UINT_C(0x80)
67
68/* シリアルステータスレジスタ(SSR) */
69#define TEND UINT_C(0x04)
70#define PER UINT_C(0x08)
71#define FER UINT_C(0x10)
72#define ORER UINT_C(0x20)
73
74/* シリアル拡張モードレジスタ(SEMR) */
75#define ACS0 UINT_C(0x01)
76#define ABCS UINT_C(0x10)
77
78#define SCI_SCR_FLG_ENABLE (RE | TE)
79#define SCI_SMR_FLG_ENABLE (STOP | PM | PE | CHR | CM)
80
81/*
82 * シリアルI/Oポート初期化ブロックの定義
83 */
84typedef struct sio_port_initialization_block {
85 volatile uint8_t *ctlreg; /* シリアルコントロールレジスタ(SCR) */
86 volatile uint8_t *modereg; /* シリアルモードレジスタ(SMR) */
87 volatile uint8_t *extmodereg; /* シリアル拡張モードレジスタ(SEMR) */
88 volatile uint8_t *statusreg; /* シリアルステータスレジスタ(SSR) */
89 volatile uint8_t *tdreg; /* トランスミットデータレジスタ(TDR)*/
90 volatile uint8_t *rdreg; /* レシーブデータレジスタ(RDR) */
91 volatile uint8_t *bitratereg; /* ビットレートレジスタ(BRR) */
92 volatile uint32_t *mstpcrreg; /* モジュールストップコントロールレジスタ(MSTPCR) */
93 volatile uint8_t *ssrreg; /* ステータスレジスタ */
94 volatile uint8_t *rxiirreg; /* RXI用割込み要求レジスタ */
95 uint8_t tx_intno; /* 送信(データエンプティ)割り込み番号 */
96 uint8_t rx_intno; /* 受信(データフル)割り込み番号 */
97 uint8_t te_intno; /* 送信(終了)割り込み番号 */
98 uint8_t sci_no; /* SCIの番号(SCI0〜SCI6) */
99 uint32_t mstpcr_offset; /* MSTPCRの対応するビットオフセット */
100} SIOPINIB;
101
102/*
103 * シリアルI/Oポート管理ブロックの定義
104 */
105struct sio_port_control_block {
106 const SIOPINIB *p_siopinib; /* シリアルI/Oポート初期化ブロック */
107 intptr_t exinf; /* 拡張情報 */
108 bool_t openflag; /* オープン済みフラグ */
109 bool_t sendflag; /* 送信割込みイネーブルフラグ */
110 bool_t getready; /* 文字を受信した状態 */
111 bool_t putready; /* 文字を送信できる状態 */
112 bool_t is_initialized; /* デバイス初期化済みフラグ */
113};
114
115/*
116 * シリアルI/Oポート管理ブロックのエリア
117 */
118static SIOPCB siopcb_table[TNUM_SIOP];
119
120/* レジスタテーブル */
121static const SIOPINIB siopinib_table[TNUM_SIOP] =
122{
123 {
124 (volatile uint8_t *)SCI0_SCR_ADDR,
125 (volatile uint8_t *)SCI0_SMR_ADDR,
126 (volatile uint8_t *)SCI0_SEMR_ADDR,
127 (volatile uint8_t *)SCI0_SSR_ADDR,
128 (volatile uint8_t *)SCI0_TDR_ADDR,
129 (volatile uint8_t *)SCI0_RDR_ADDR,
130 (volatile uint8_t *)SCI0_BRR_ADDR,
131 (volatile uint32_t *)SYSTEM_MSTPCRB_ADDR,
132 (volatile uint8_t *)SCI0_SSR_ADDR,
133 (volatile uint8_t *)ICU_IR215_ADDR,
134 INT_SCI0_TXI,
135 INT_SCI0_RXI,
136 INT_SCI0_TEI,
137 0,
138 SYSTEM_MSTPCRB_MSTPB31_BIT,
139 } , /* UART0 */
140#if TNUM_SIOP > 1
141 {
142 (volatile uint8_t *)SCI2_SCR_ADDR,
143 (volatile uint8_t *)SCI2_SMR_ADDR,
144 (volatile uint8_t *)SCI2_SEMR_ADDR,
145 (volatile uint8_t *)SCI2_SSR_ADDR,
146 (volatile uint8_t *)SCI2_TDR_ADDR,
147 (volatile uint8_t *)SCI2_RDR_ADDR,
148 (volatile uint8_t *)SCI2_BRR_ADDR,
149 (volatile uint32_t *)SYSTEM_MSTPCRB_ADDR,
150 (volatile uint8_t *)SCI2_SSR_ADDR,
151 (volatile uint8_t *)ICU_IR223_ADDR,
152 INT_SCI2_TXI,
153 INT_SCI2_RXI,
154 INT_SCI2_TEI,
155 2,
156 SYSTEM_MSTPCRB_MSTPB29_BIT,
157 } , /* UART2 */
158#endif
159};
160
161/*
162 * シリアルI/OポートIDから管理ブロックを取り出すためのマクロ
163 */
164#define INDEX_SIOP(siopid) ((uint_t)((siopid) - 1))
165#define get_siopcb(siopid) (&(siopcb_table[INDEX_SIOP(siopid)]))
166#define get_siopinib(siopid) (&(siopinib_table[INDEX_SIOP(siopid)]))
167
168
169/*
170 * SIOドライバのシリアルモードレジスタ(SMR)
171 */
172static void
173rx630_uart_setmode(const SIOPINIB *p_siopinib, uint8_t bitrate, uint8_t clksrc)
174{
175 volatile uint8_t i;
176
177 /*
178 * SCIドライバの初期化ルーチン
179 */
180
181 /*
182 * 割り込み要求先レジスタの設定(ISELRi)
183 *
184 * リセット値と同じ値を設定することになるため,
185 * 処理は省略する.
186 */
187
188 /*
189 * モジュールストップ機能の設定
190 */
191 sil_wrh_mem(SYSTEM_PRCR_ADDR, (uint16_t)0xA502); /* 書込み許可 */
192 sil_wrw_mem(p_siopinib->mstpcrreg,
193 sil_rew_mem(p_siopinib->mstpcrreg) & ~p_siopinib->mstpcr_offset);
194 sil_wrh_mem(SYSTEM_PRCR_ADDR, (uint16_t)0xA500); /* 書込み禁止 */
195
196 /* 送受信禁止, SCKn端子は入出力ポートとして使用 */
197 sil_wrb_mem(p_siopinib->ctlreg, 0x00U);
198
199 /* クロック選択ビット(SMR.CKS[1:0]ビットを設定) */
200 sil_wrb_mem(p_siopinib->modereg,
201 sil_reb_mem(p_siopinib->modereg) | clksrc);
202
203 /* SMRに送信/ 受信フォーマットを設定) */
204 sil_wrb_mem(p_siopinib->modereg,
205 sil_reb_mem(p_siopinib->modereg) & (~SCI_SMR_FLG_ENABLE));
206
207 /* ビットレートを設定 */
208 sil_wrb_mem(p_siopinib->bitratereg, bitrate);
209
210 /* ビット期間(基本クロック16サイクルの期間が1ビット期間となる) */
211 for(i = 0; i < 16; i++) { }
212
213 /* 送受信許可 */
214 sil_wrb_mem(p_siopinib->ctlreg,
215 (sil_reb_mem(p_siopinib->ctlreg) | SCI_SCR_FLG_ENABLE));
216}
217
218
219/*
220 * SIOドライバの初期化ルーチン
221 */
222void
223rx630_uart_initialize(void)
224{
225 SIOPCB *p_siopcb;
226 uint_t i;
227
228 /*
229 * シリアルI/Oポート管理ブロックの初期化
230 */
231 for (p_siopcb = siopcb_table, i = 0; i < TNUM_SIOP; p_siopcb++, i++){
232 p_siopcb->p_siopinib = &(siopinib_table[i]);
233 p_siopcb->openflag = false;
234 p_siopcb->sendflag = false;
235 }
236}
237
238/*
239 * カーネル起動時のバナー出力用の初期化
240 */
241void
242rx630_uart_init(ID siopid, uint8_t bitrate, uint8_t clksrc)
243{
244 SIOPCB *p_siopcb = get_siopcb(siopid);
245 const SIOPINIB *p_siopinib = get_siopinib(siopid);
246 /* この時点では、p_siopcb->p_siopinibは初期化されていない */
247
248 /* 二重初期化の防止 */
249 p_siopcb->is_initialized = true;
250
251 /* ハードウェアの初期化処理と送信許可 */
252 rx630_uart_setmode(p_siopinib , bitrate, clksrc);
253 sil_wrb_mem(p_siopinib->ctlreg,
254 (uint8_t)(sil_reb_mem(p_siopinib->ctlreg) | TE));
255}
256
257/*
258 * シリアルI/Oポートへのポーリングでの出力
259 */
260void
261rx630_uart_pol_putc(char c, ID siopid)
262{
263 const SIOPINIB *p_siopinib;
264
265 p_siopinib = get_siopinib(siopid);
266
267 /*
268 * 送信レジスタが空になるまで待つ
269 */
270 while((sil_reb_mem(p_siopinib->ssrreg) & SCI_SSR_TEND_BIT) == 0U);
271
272 sil_wrb_mem(p_siopinib->tdreg, (uint8_t)c);
273}
274
275/*
276 * シリアルI/Oポートのオープン
277 */
278SIOPCB *
279rx630_uart_opn_por
280 (ID siopid, intptr_t exinf, uint8_t bitrate, uint8_t clksrc)
281{
282 SIOPCB *p_siopcb;
283 const SIOPINIB *p_siopinib;
284
285 p_siopcb = get_siopcb(siopid);
286 p_siopinib = p_siopcb->p_siopinib;
287
288 /*
289 * ハードウェアの初期化
290 *
291 * 既に初期化している場合は, 二重に初期化しない.
292 */
293 if(!(p_siopcb->is_initialized)){
294 rx630_uart_setmode(p_siopinib, bitrate, clksrc);
295 p_siopcb->is_initialized = true;
296 }
297
298 p_siopcb->exinf = exinf;
299 p_siopcb->getready = p_siopcb->putready = false;
300 p_siopcb->openflag = true;
301
302 return (p_siopcb);
303}
304
305/*
306 * シリアルI/Oポートのクローズ
307 */
308void
309rx630_uart_cls_por(SIOPCB *p_siopcb)
310{
311 /*
312 * UART停止
313 */
314 sil_wrh_mem(p_siopcb->p_siopinib->ctlreg, 0x00U);
315 p_siopcb->openflag = false;
316 p_siopcb->is_initialized = false;
317}
318
319/*
320 * シリアルI/Oポートへの文字送信
321 */
322bool_t
323rx630_uart_snd_chr(SIOPCB *p_siopcb, char c)
324{
325 bool_t ercd = false;
326
327 if((sil_reb_mem(
328 (uint8_t *)p_siopcb->p_siopinib->ssrreg) & SCI_SSR_TEND_BIT) != 0){
329 sil_wrb_mem(p_siopcb->p_siopinib->tdreg, (uint8_t)c);
330 ercd = true;
331 }
332
333 return ercd;
334}
335
336/*
337 * シリアルI/Oポートからの文字受信
338 */
339int_t
340rx630_uart_rcv_chr(SIOPCB *p_siopcb)
341{
342 int_t c = -1;
343
344 /*
345 * 受信フラグがONのときのみ受信バッファから文字を取得する.
346 * これは, ポーリング受信に対応するためである.
347 * しかし, RX600シリーズでは受信フラグがないこと, システムサービス
348 * では受信割込みの中からしかデータを受信しに来ないことから, 常に
349 * 受信バッファから文字を取得する.
350 */
351 c = (int)(sil_reb_mem(p_siopcb->p_siopinib->rdreg));
352
353 return c;
354}
355
356/*
357 * シリアルI/Oポートからのコールバックの許可
358 */
359void
360rx630_uart_ena_cbr(SIOPCB *p_siopcb, uint_t cbrtn)
361{
362 switch (cbrtn) {
363 case SIO_RDY_SND:
364 sil_wrb_mem(p_siopcb->p_siopinib->ctlreg,
365 (sil_reb_mem(p_siopcb->p_siopinib->ctlreg) | SCI_SCR_TEIE_BIT));
366 break;
367 case SIO_RDY_RCV:
368 sil_wrb_mem(p_siopcb->p_siopinib->ctlreg,
369 (sil_reb_mem(p_siopcb->p_siopinib->ctlreg) | SCI_SCR_RIE_BIT));
370 break;
371 default:
372 assert(1);
373 break;
374 }
375}
376
377/*
378 * シリアルI/Oポートからのコールバックの禁止
379 */
380void
381rx630_uart_dis_cbr(SIOPCB *p_siopcb, uint_t cbrtn)
382{
383 switch (cbrtn) {
384 case SIO_RDY_SND:
385 sil_wrb_mem(p_siopcb->p_siopinib->ctlreg,
386 (sil_reb_mem(p_siopcb->p_siopinib->ctlreg) & (~SCI_SCR_TEIE_BIT)));
387 break;
388 case SIO_RDY_RCV:
389 sil_wrb_mem(p_siopcb->p_siopinib->ctlreg,
390 (sil_reb_mem(p_siopcb->p_siopinib->ctlreg) & (~SCI_SCR_RIE_BIT)));
391 break;
392 default:
393 assert(1);
394 break;
395 }
396}
397
398/*
399 * SIOの割込みサービスルーチン
400 */
401void
402rx630_uart_tx_isr(ID siopid)
403{
404 SIOPCB *p_siopcb = get_siopcb(siopid);
405
406 if((sil_reb_mem(
407 (void *)p_siopcb->p_siopinib->ssrreg) & SCI_SSR_TEND_BIT) != 0U){
408 /*
409 * 送信可能コールバックルーチンを呼び出す.
410 */
411 rx630_uart_irdy_snd(p_siopcb->exinf);
412 }
413}
414
415void
416rx630_uart_rx_isr(ID siopid)
417{
418 SIOPCB *p_siopcb = get_siopcb(siopid);
419
420 /*
421 * 受信フラグがONのときのみ受信通知コールバックルーチンを呼び出す.
422 * しかし, RX600シリーズでは受信フラグがないため, 常に受信通知
423 * コールバックルーチンを呼び出す.
424 * ここでは受信割込みの発生を信じる.
425 */
426 /*
427 * 受信通知コールバックルーチンを呼び出す.
428 */
429 rx630_uart_irdy_rcv(p_siopcb->exinf);
430}
431
432
433/*
434 * ポート番号から管理ブロックの先頭番地への変換
435 */
436SIOPCB *
437rx630_uart_get_siopcb(ID siopid) {
438 SIOPCB *p_siopcb = get_siopcb(siopid);
439 return(p_siopcb);
440}
441
442/*
443 * 管理ブロックの先頭番地から受信割込み番号への変換
444 */
445INTNO
446rx630_uart_intno_rx(SIOPCB *p_siopcb) {
447 INTNO intno = p_siopcb->p_siopinib->rx_intno;
448 return(intno);
449}
450
451/*
452 * 管理ブロックの先頭番地から送信割込み番号への変換
453 */
454INTNO
455rx630_uart_intno_tx(SIOPCB *p_siopcb) {
456 INTNO intno = p_siopcb->p_siopinib->te_intno;
457 return(intno);
458}
Note: See TracBrowser for help on using the repository browser.