/* * TOPPERS/ASP Kernel * Toyohashi Open Platform for Embedded Real-Time Systems/ * Advanced Standard Profile Kernel * * Copyright (C) 2007 by Embedded and Real-Time Systems Laboratory * Graduate School of Information Science, Nagoya Univ., JAPAN * * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する. * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー * スコード中に含まれていること. * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 * の無保証規定を掲載すること. * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ * と. * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 * 作権表示,この利用条件および下記の無保証規定を掲載すること. * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに * 報告すること. * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを * 免責すること. * * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ * の責任を負わない. * */ /* * シリアルドライバ(FS K70用) */ #include #include #include "target_serial.h" #include "target_syssvc.h" /* * レジスタ設定値 */ #define PORT2SIOPID(x) ((x) + 1) #define INDEX_PORT(x) ((x) - 1) #define GET_SIOPCB(x) (&siopcb_table[INDEX_PORT(x)]) /* * UARTレジスタ定義 */ #define UART_BDH(x) (x) #define UART_BDL(x) (x + 0x01) #define UART_C1(x) (x + 0x02) #define UART_C2(x) (x + 0x03) #define UART_S1(x) (x + 0x04) #define UART_C3(x) (x + 0x06) #define UART_D(x) (x + 0x07) #define UART_C4(x) (x + 0x0A) #define S1_TDRE (0x80) #define S1_TC (0x40) #define S1_RDRF (0x20) #define S1_OR (0x08) #define S1_FE (0x02) #define S1_PE (0x01) #define C2_TIE (0x80) #define C2_TCIE (0x40) #define C2_RIE (0x20) #define C2_TE (0x08) #define C2_RE (0x04) #define C3_ORIE (0x08) #define C3_NEIE (0x04) #define C3_FEIE (0x02) #define C3_PEIE (0x01) /* * シリアルI/Oポート管理ブロックエリア */ SIOPCB siopcb_table[TNUM_PORT]; static const uint32_t sioreg_table[TNUM_PORT] = { UART2_BASE, }; #pragma inline bool_t sio_putready(SIOPCB* siopcb) { return (sil_reb_mem((void*)UART_S1(siopcb->reg)) & S1_TC) != 0; } #pragma inline bool_t sio_getready(SIOPCB* siopcb) { return (sil_reb_mem((void*)UART_S1(siopcb->reg)) & S1_RDRF) != 0; } /* * ターゲットのシリアル初期化 */ void target_uart_init(ID siopid) { uint32_t tmp, brfa; uint32_t reg = sioreg_table[INDEX_PORT(siopid)]; uint32_t src_clock; /* UARTの無効化 */ sil_andb((void*)UART_C2(reg), ~(C2_TE|C2_RE)); /* 1STOP BIT, 1START BIT, 8DATA bits, Parityなし */ sil_wrb_mem((void*)UART_C1(reg), 0); /* fck=60MHz */ src_clock = BUS_CLOCK; tmp = src_clock / (BPS_SETTING * 16); sil_wrb_mem( (void*)UART2_BDH, (sil_reb_mem( (void*)UART2_BDH ) & ~(0x1F)) | ((tmp & 0x1F00) >> 8) ); sil_wrb_mem( (void*)UART2_BDL, (char_t)(tmp & 0xFF) ); brfa = (((src_clock / 1000 * 32000) / (BPS_SETTING * 16)) - (tmp * 32) ); sil_wrb_mem( (void*)UART2_C4, (sil_reb_mem( (void*)UART2_C4 ) & ~(0x1F)) | (brfa & 0x1F) ); /* エラー割込みの有効化 */ sil_orb((void*)UART_C3(reg), (C3_ORIE|C3_NEIE|C3_FEIE|C3_PEIE)); /* 送受信の有効化 */ sil_orb( (void*)UART2_C2, (C2_RIE|C2_TE|C2_RE) ); } /* * ターゲットのシリアル終了 */ void target_uart_term(ID siopid) { uint32_t reg = sioreg_table[INDEX_PORT(siopid)]; /* UARTの無効化 */ sil_andb((void*)UART_C2(reg), ~(C2_TE|C2_RE)); } /* * SIO初期化 */ void sio_initialize(intptr_t exinf) { int i; for (i = 0; i < TNUM_PORT; i++) { siopcb_table[i].port = i; siopcb_table[i].reg = sioreg_table[i]; siopcb_table[i].exinf = 0; } } /* * シリアルオープン */ SIOPCB *sio_opn_por(ID siopid, intptr_t exinf) { SIOPCB* siopcb; if (siopid > TNUM_PORT) { return NULL; } siopcb = GET_SIOPCB(siopid); siopcb->exinf = exinf; target_uart_init(siopid); return siopcb; } /* * シリアルクローズ */ void sio_cls_por(SIOPCB *p_siopcb) { target_uart_term(PORT2SIOPID(p_siopcb->port)); } /* * 割込みハンドラ */ void sio_isr(intptr_t exinf) { SIOPCB* siopcb = GET_SIOPCB(exinf); if (sio_putready(siopcb)) { sio_irdy_snd(siopcb->exinf); } if (sio_getready(siopcb)) { sio_irdy_rcv(siopcb->exinf); } } /* * 1文字送信 */ bool_t sio_snd_chr(SIOPCB *siopcb, char c) { bool_t stat; if (sio_putready(siopcb)) { sil_wrb_mem((void*)UART_D(siopcb->reg), c); stat = true; } else { stat = false; } return stat; } /* * 1文字受信 */ int_t sio_rcv_chr(SIOPCB *siopcb) { int_t c = -1; if (sio_getready(siopcb)) { c = sil_reb_mem((void*)UART_D(siopcb->reg)); } return c; } /* * コールバックの許可 */ void sio_ena_cbr(SIOPCB *siopcb, uint_t cbrtn) { switch (cbrtn) { case SIO_RDY_SND: sil_orb((void*)UART_C2(siopcb->reg), C2_TCIE); break; case SIO_RDY_RCV: sil_orb((void*)UART_C2(siopcb->reg), C2_RIE); break; default: break; } } /* * コールバックの禁止 */ void sio_dis_cbr(SIOPCB *siopcb, uint_t cbrtn) { switch (cbrtn) { case SIO_RDY_SND: sil_andb((void*)UART_C2(siopcb->reg), ~C2_TCIE); break; case SIO_RDY_RCV: sil_andb((void*)UART_C2(siopcb->reg), ~C2_RIE); break; default: break; } } /* * 1文字出力(ポーリングでの出力) */ void sio_pol_snd_chr(char_t c, ID siopid) { uint32_t reg = sioreg_table[INDEX_PORT(siopid)]; sil_wrb_mem((void*)UART_D(reg), c); while ((sil_reb_mem((void*)UART_S1(reg)) & S1_TC) == 0) ; }