upd72001.c

説明を見る。
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.

ホームページ制作