source: UsbWattMeter/trunk/asp_dcre/pdic/rx600/rx630_uart.c@ 167

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

MIMEにSJISを設定

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