00001 /* 00002 * TOPPERS/ASP Kernel 00003 * Toyohashi Open Platform for Embedded Real-Time Systems/ 00004 * Advanced Standard Profile Kernel 00005 * 00006 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory 00007 * Toyohashi Univ. of Technology, JAPAN 00008 * Copyright (C) 2006-2008 by Embedded and Real-Time Systems Laboratory 00009 * Graduate School of Information Science, Nagoya Univ., JAPAN 00010 * 00011 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ 00012 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改 00013 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する. 00014 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 00015 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー 00016 * スコード中に含まれていること. 00017 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 00018 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 00019 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 00020 * の無保証規定を掲載すること. 00021 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 00022 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ 00023 * と. 00024 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 00025 * 作権表示,この利用条件および下記の無保証規定を掲載すること. 00026 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに 00027 * 報告すること. 00028 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 00029 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. 00030 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理 00031 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを 00032 * 免責すること. 00033 * 00034 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お 00035 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的 00036 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ 00037 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ 00038 * の責任を負わない. 00039 * 00040 * @(#) $Id: upd72001.c 873 2008-04-11 10:32:26Z hiro $ 00041 */ 00042 00043 /* 00044 * μPD72001用 簡易SIOドライバ 00045 */ 00046 00047 #include <sil.h> 00048 #include "target_syssvc.h" 00049 #include "upd72001.h" 00050 00051 /* 00052 * デバイスレジスタのアクセス間隔時間(nsec単位) 00053 * 00054 * 200という値にあまり根拠はない. 00055 */ 00056 #define UPD72001_DELAY 200U 00057 00058 /* 00059 * μPD72001のレジスタの番号 00060 */ 00061 #define UPD72001_CR0 0x00U /* コントロールレジスタ */ 00062 #define UPD72001_CR1 0x01U 00063 #define UPD72001_CR2 0x02U 00064 #define UPD72001_CR3 0x03U 00065 #define UPD72001_CR4 0x04U 00066 #define UPD72001_CR5 0x05U 00067 #define UPD72001_CR10 0x0aU 00068 #define UPD72001_CR12 0x0cU 00069 #define UPD72001_CR14 0x0eU 00070 #define UPD72001_CR15 0x0fU 00071 00072 #define UPD72001_SR0 0x00U /* ステータスレジスタ */ 00073 00074 /* 00075 * コントロールレジスタの設定値 00076 */ 00077 #define CR_RESET 0x18U /* ポートリセットコマンド */ 00078 00079 #define CR0_EOI 0x38U /* EOI(End of Interrupt)*/ 00080 00081 #define CR1_DOWN 0x00U /* 全割込みを禁止 */ 00082 #define CR1_RECV 0x10U /* 受信割込み許可ビット */ 00083 #define CR1_SEND 0x02U /* 送信割込み許可ビット */ 00084 00085 #define CR3_DEF 0xc1U /* データ 8bit,受信イネーブル */ 00086 #define CR4_DEF 0x44U /* ストップビット 1bit,パリティなし */ 00087 #define CR5_DEF 0xeaU /* データ 8bit,送信イネーブル */ 00088 00089 #define CR10_DEF 0x00U /* NRZ */ 00090 #define CR14_DEF 0x07U /* ボーレートジェネレータイネーブル */ 00091 #define CR15_DEF 0x56U /* ボーレートジェネレータ使用 */ 00092 00093 #define SR0_RECV 0x01U /* 受信通知ビット */ 00094 #define SR0_SEND 0x04U /* 送信可能ビット */ 00095 00096 /* 00097 * シリアルI/Oポート初期化ブロックの定義 00098 */ 00099 typedef struct sio_port_initialization_block { 00100 void *data; /* データレジスタの番地 */ 00101 void *ctrl; /* コントロールレジスタの番地 */ 00102 00103 uint8_t cr3_def; /* CR3の設定値(受信ビット数)*/ 00104 uint8_t cr4_def; /* CR4の設定値(ストップビット,パリティ)*/ 00105 uint8_t cr5_def; /* CR5の設定値(送信ビット数)*/ 00106 uint8_t brg1_def; /* ボーレート上位の設定値 */ 00107 uint8_t brg2_def; /* ボーレート下位の設定値 */ 00108 } SIOPINIB; 00109 00110 /* 00111 * シリアルI/Oポート管理ブロックの定義 00112 */ 00113 struct sio_port_control_block { 00114 const SIOPINIB *p_siopinib; /* シリアルI/Oポート初期化ブロック */ 00115 intptr_t exinf; /* 拡張情報 */ 00116 bool_t openflag; /* オープン済みフラグ */ 00117 uint8_t cr1; /* CR1の設定値(割込み許可)*/ 00118 bool_t getready; /* 文字を受信した状態 */ 00119 bool_t putready; /* 文字を送信できる状態 */ 00120 }; 00121 00122 /* 00123 * シリアルI/Oポート初期化ブロック 00124 */ 00125 const SIOPINIB siopinib_table[TNUM_SIOP] = { 00126 { (void *) TADR_UPD72001_DATAA, (void *) TADR_UPD72001_CTRLA, 00127 CR3_DEF, CR4_DEF, CR5_DEF, BRG1_DEF, BRG2_DEF }, 00128 { (void *) TADR_UPD72001_DATAB, (void *) TADR_UPD72001_CTRLB, 00129 CR3_DEF, CR4_DEF, CR5_DEF, BRG1_DEF, BRG2_DEF } 00130 }; 00131 00132 /* 00133 * シリアルI/Oポート管理ブロックのエリア 00134 */ 00135 SIOPCB siopcb_table[TNUM_SIOP]; 00136 00137 /* 00138 * シリアルI/OポートIDから管理ブロックを取り出すためのマクロ 00139 */ 00140 #define INDEX_SIOP(siopid) ((uint_t)((siopid) - 1)) 00141 #define get_siopcb(siopid) (&(siopcb_table[INDEX_SIOP(siopid)])) 00142 00143 /* 00144 * デバイスレジスタへのアクセス関数 00145 */ 00146 Inline uint8_t 00147 upd72001_read_reg(void *addr) 00148 { 00149 uint8_t val; 00150 00151 val = upd72001_reb_reg(addr); 00152 sil_dly_nse(UPD72001_DELAY); 00153 return(val); 00154 } 00155 00156 Inline void 00157 upd72001_write_reg(void *addr, uint8_t val) 00158 { 00159 upd72001_wrb_reg(addr, val); 00160 sil_dly_nse(UPD72001_DELAY); 00161 } 00162 00163 Inline uint8_t 00164 upd72001_read_ctrl(void *addr, uint8_t reg) 00165 { 00166 upd72001_write_reg(addr, reg); 00167 return(upd72001_read_reg(addr)); 00168 } 00169 00170 Inline void 00171 upd72001_write_ctrl(void *addr, uint8_t reg, uint8_t val) 00172 { 00173 upd72001_write_reg(addr, reg); 00174 upd72001_write_reg(addr, val); 00175 } 00176 00177 Inline void 00178 upd72001_write_brg(void *addr, uint8_t reg, uint8_t val, 00179 uint8_t brg2, uint8_t brg1) 00180 { 00181 upd72001_write_reg(addr, reg); 00182 upd72001_write_reg(addr, val); 00183 upd72001_write_reg(addr, brg2); 00184 upd72001_write_reg(addr, brg1); 00185 (void) upd72001_read_reg(addr); /* ダミーリード */ 00186 } 00187 00188 /* 00189 * 状態の読出し(SR0の読出し) 00190 * 00191 * μPD72001は,状態(SR0)を一度読むと受信通知ビットが落ちてしまうた 00192 * め,状態を読み出す関数を設け,シリアルI/Oポート管理ブロック中の 00193 * getreadyに受信通知状態,putreadyに送信可能状態を保存している(送信 00194 * 可能状態の保存は不要かもしれない). 00195 * 状態レジスタを読んでも受信通知ビットが落ちないデバイス(こちらが普 00196 * 通と思われる)では,この関数は必要ない. 00197 */ 00198 static void 00199 upd72001_get_stat(SIOPCB *p_siopcb) 00200 { 00201 uint8_t sr0; 00202 00203 sr0 = upd72001_read_ctrl(p_siopcb->p_siopinib->ctrl, UPD72001_SR0); 00204 if ((sr0 & SR0_RECV) != 0) { 00205 p_siopcb->getready = true; 00206 } 00207 if ((sr0 & SR0_SEND) != 0) { 00208 p_siopcb->putready = true; 00209 } 00210 } 00211 00212 /* 00213 * 文字を受信できるか? 00214 */ 00215 Inline bool_t 00216 upd72001_getready(SIOPCB *p_siopcb) 00217 { 00218 upd72001_get_stat(p_siopcb); 00219 return(p_siopcb->getready); 00220 } 00221 00222 /* 00223 * 文字を送信できるか? 00224 */ 00225 Inline bool_t 00226 upd72001_putready(SIOPCB *p_siopcb) 00227 { 00228 upd72001_get_stat(p_siopcb); 00229 return(p_siopcb->putready); 00230 } 00231 00232 /* 00233 * 受信した文字の取出し 00234 */ 00235 Inline char_t 00236 upd72001_getchar(SIOPCB *p_siopcb) 00237 { 00238 p_siopcb->getready = false; 00239 return((char_t) upd72001_read_reg(p_siopcb->p_siopinib->data)); 00240 } 00241 00242 /* 00243 * 送信する文字の書込み 00244 */ 00245 Inline void 00246 upd72001_putchar(SIOPCB *p_siopcb, char_t c) 00247 { 00248 p_siopcb->putready = false; 00249 upd72001_write_reg(p_siopcb->p_siopinib->data, (uint8_t) c); 00250 } 00251 00252 /* 00253 * EOI(End Of Interrupt)発行 00254 */ 00255 Inline void 00256 upd72001_eoi(void) 00257 { 00258 upd72001_write_ctrl((void *) TADR_UPD72001_CTRLA, UPD72001_CR0, CR0_EOI); 00259 } 00260 00261 /* 00262 * SIOドライバの初期化 00263 */ 00264 void 00265 upd72001_initialize(void) 00266 { 00267 SIOPCB *p_siopcb; 00268 uint_t i; 00269 00270 /* 00271 * シリアルI/Oポート管理ブロックの初期化 00272 */ 00273 for (p_siopcb = siopcb_table, i = 0; i < TNUM_SIOP; p_siopcb++, i++) { 00274 p_siopcb->p_siopinib = &(siopinib_table[i]); 00275 p_siopcb->openflag = false; 00276 } 00277 } 00278 00279 /* 00280 * オープンしているポートがあるか? 00281 */ 00282 bool_t 00283 upd72001_openflag(void) 00284 { 00285 return(siopcb_table[0].openflag || siopcb_table[1].openflag); 00286 } 00287 00288 /* 00289 * シリアルI/Oポートのオープン 00290 */ 00291 SIOPCB * 00292 upd72001_opn_por(ID siopid, intptr_t exinf) 00293 { 00294 SIOPCB *p_siopcb; 00295 const SIOPINIB *p_siopinib; 00296 00297 p_siopcb = get_siopcb(siopid); 00298 p_siopinib = p_siopcb->p_siopinib; 00299 00300 upd72001_write_reg(p_siopinib->ctrl, CR_RESET); 00301 if (!upd72001_openflag()) { 00302 upd72001_write_ctrl((void *) TADR_UPD72001_CTRLA, UPD72001_CR2, 0x18); 00303 upd72001_write_ctrl((void *) TADR_UPD72001_CTRLB, UPD72001_CR2, 0x00); 00304 } 00305 p_siopcb->cr1 = CR1_DOWN; 00306 upd72001_write_ctrl(p_siopinib->ctrl, UPD72001_CR1, p_siopcb->cr1); 00307 upd72001_write_ctrl(p_siopinib->ctrl, UPD72001_CR4, p_siopinib->cr4_def); 00308 upd72001_write_brg(p_siopinib->ctrl, UPD72001_CR12, 0x01U, 00309 p_siopinib->brg2_def, p_siopinib->brg1_def); 00310 upd72001_write_brg(p_siopinib->ctrl, UPD72001_CR12, 0x02U, 00311 p_siopinib->brg2_def, p_siopinib->brg1_def); 00312 upd72001_write_ctrl(p_siopinib->ctrl, UPD72001_CR15, CR15_DEF); 00313 upd72001_write_ctrl(p_siopinib->ctrl, UPD72001_CR14, CR14_DEF); 00314 upd72001_write_ctrl(p_siopinib->ctrl, UPD72001_CR10, CR10_DEF); 00315 upd72001_write_ctrl(p_siopinib->ctrl, UPD72001_CR3, p_siopinib->cr3_def); 00316 upd72001_write_ctrl(p_siopinib->ctrl, UPD72001_CR5, p_siopinib->cr5_def); 00317 p_siopcb->exinf = exinf; 00318 p_siopcb->getready = p_siopcb->putready = false; 00319 p_siopcb->openflag = true; 00320 return(p_siopcb); 00321 } 00322 00323 /* 00324 * シリアルI/Oポートのクローズ 00325 */ 00326 void 00327 upd72001_cls_por(SIOPCB *p_siopcb) 00328 { 00329 upd72001_write_ctrl(p_siopcb->p_siopinib->ctrl, UPD72001_CR1, CR1_DOWN); 00330 p_siopcb->openflag = false; 00331 } 00332 00333 /* 00334 * シリアルI/Oポートへの文字送信 00335 */ 00336 bool_t 00337 upd72001_snd_chr(SIOPCB *p_siopcb, char_t c) 00338 { 00339 if (upd72001_putready(p_siopcb)) { 00340 upd72001_putchar(p_siopcb, c); 00341 return(true); 00342 } 00343 return(false); 00344 } 00345 00346 /* 00347 * シリアルI/Oポートからの文字受信 00348 */ 00349 int_t 00350 upd72001_rcv_chr(SIOPCB *p_siopcb) 00351 { 00352 if (upd72001_getready(p_siopcb)) { 00353 return((int_t)(uint8_t) upd72001_getchar(p_siopcb)); 00354 } 00355 return(-1); 00356 } 00357 00358 /* 00359 * シリアルI/Oポートからのコールバックの許可 00360 */ 00361 void 00362 upd72001_ena_cbr(SIOPCB *p_siopcb, uint_t cbrtn) 00363 { 00364 uint8_t cr1_bit = 0; 00365 00366 switch (cbrtn) { 00367 case SIO_RDY_SND: 00368 cr1_bit = CR1_SEND; 00369 break; 00370 case SIO_RDY_RCV: 00371 cr1_bit = CR1_RECV; 00372 break; 00373 } 00374 p_siopcb->cr1 |= cr1_bit; 00375 upd72001_write_ctrl(p_siopcb->p_siopinib->ctrl, 00376 UPD72001_CR1, p_siopcb->cr1); 00377 } 00378 00379 /* 00380 * シリアルI/Oポートからのコールバックの禁止 00381 */ 00382 void 00383 upd72001_dis_cbr(SIOPCB *p_siopcb, uint_t cbrtn) 00384 { 00385 uint8_t cr1_bit = 0; 00386 00387 switch (cbrtn) { 00388 case SIO_RDY_SND: 00389 cr1_bit = CR1_SEND; 00390 break; 00391 case SIO_RDY_RCV: 00392 cr1_bit = CR1_RECV; 00393 break; 00394 } 00395 p_siopcb->cr1 &= ~cr1_bit; 00396 upd72001_write_ctrl(p_siopcb->p_siopinib->ctrl, 00397 UPD72001_CR1, p_siopcb->cr1); 00398 } 00399 00400 /* 00401 * シリアルI/Oポートに対する割込み処理 00402 */ 00403 static void 00404 upd72001_isr_siop(SIOPCB *p_siopcb) 00405 { 00406 if ((p_siopcb->cr1 & CR1_RECV) != 0U && upd72001_getready(p_siopcb)) { 00407 /* 00408 * 受信通知コールバックルーチンを呼び出す. 00409 */ 00410 upd72001_irdy_rcv(p_siopcb->exinf); 00411 } 00412 if ((p_siopcb->cr1 & CR1_SEND) != 0U && upd72001_putready(p_siopcb)) { 00413 /* 00414 * 送信可能コールバックルーチンを呼び出す. 00415 */ 00416 upd72001_irdy_snd(p_siopcb->exinf); 00417 } 00418 } 00419 00420 /* 00421 * SIOの割込みサービスルーチン 00422 */ 00423 void 00424 upd72001_isr(void) 00425 { 00426 if (siopcb_table[0].openflag) { 00427 upd72001_isr_siop(&(siopcb_table[0])); 00428 } 00429 if (siopcb_table[1].openflag) { 00430 upd72001_isr_siop(&(siopcb_table[1])); 00431 } 00432 upd72001_eoi(); 00433 }
Copyright © 2008 by Kijineko Inc.