/* * TOPPERS/SSP 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 * Copyright (C) 2010 by Meika Sugimoto * Copyright (C) 2011-2015 by Naoki Saito * Nagoya Municipal Industrial Research Institute, JAPAN * * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する. * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー * スコード中に含まれていること. * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 * の無保証規定を掲載すること. * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ * と. * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 * 作権表示,この利用条件および下記の無保証規定を掲載すること. * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに * 報告すること. * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを * 免責すること. * * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ * の責任を負わない. * */ /* * シリアルドライバ(QB-R5F100LE用) */ #pragma sfr #pragma NOP #include #include "target_serial.h" #include "target_syssvc.h" /* * シリアルI/Oポート管理ブロックエリア */ static SIOPCB siopcb_table[TNUM_SIOP]; /* * レジスタ設定値 */ #define PORT2SIOPID(x) ((x) + 1) #define INDEX_PORT(x) ((x) - 1) #define GET_SIOPCB(x) (&siopcb_table[INDEX_PORT(x)]) extern void x_clear_int(INTNO intno); /* * 低レベルシリアル初期化 */ void target_sau_init(ID siopid) { /* 初期化済みの場合はすぐにリターン */ if(PER0 & TBIT_PER0_SAU0EN) { return; } /* クロック供給許可 */ PER0 |= TBIT_PER0_SAU0EN; // 少し待つ NOP(); NOP(); NOP(); // CKm0 を選択.周波数は fclk/8 (=2.5MHz) SPS0 = UINT16_C(0x0033); // ユニット0,チャネル{0,1} の動作停止 ST0 |= UINT16_C(0x0003); // モード設定 // 動作クロック:SPS0レジスタで設定した動作クロックのうち,CK00 の方を使う // 転送クロック:CKS00, CKS01 ビットで指定した動作クロック(つまりCK00)の分周クロック // スタートトリガ要因:送信-->ソフトウェアトリガのみ, 受信-->RxD0端子 // 立下りをスタートビットとして検出 // UARTモード,割り込みは転送完了割込み SMR00 = UINT16_C(0x0022); SMR01 = UINT16_C(0x0122); // チャネル0: 送信のみ許可,チャネル1: 受信のみ許可 // エラー割込みINTSRExの発生を禁止 // パリティなし,LSBファースト,1ストップビット,8ビットデータ長 SCR00 = UINT16_C(0x8097); SCR01 = UINT16_C(0x4097); // [ビット15:9] = 0x40 --> 64 // シリアルへの供給クロックは 2.5MHz(=20/8) // 分周比は (64+1)*2 = 130 // 2.5[MHz]/130 = 19.23[kHz] SDR00 = UINT16_C(0x8000); SDR01 = UINT16_C(0x8000); // 受信ポートのノイズフィルタON NFEN0 |= UINT8_C(0x01); // エラーフラグのクリア(受信側のチャネル1のみ) SIR01 |= UINT16_C(0x0007); // シリアルデータ出力値をチャネル0のみ1とする. SO0 |= UINT16_C(0x0001); // 通信データは反転せずそのまま出力 SOL0 = UINT16_C(0x0000); /* * シリアルチャネル0開始 */ // シリアル出力許可 SOE0 |= UINT16_C(0x0001); // チャネル{0,1}の開始 SS0 |= UINT16_C(0x0003); } /* * SIO初期化 */ void sio_initialize(intptr_t exinf) { } /* * シリアルオープン */ SIOPCB *sio_opn_por(ID siopid, intptr_t exinf) { int_t i; SIOPCB* p_siopcb; if (siopid > TNUM_PORT) { return NULL; } p_siopcb = GET_SIOPCB(siopid); p_siopcb->enacb &= ~TBIT_ENACB_SND; p_siopcb->enacb &= ~TBIT_ENACB_RCV; p_siopcb->exinf = exinf; // 割込みのマスク dis_int(INTNO_INTST0); dis_int(INTNO_INTSR0); // 割込み要求クリア x_clear_int(INTNO_INTST0); x_clear_int(INTNO_INTSR0); // ハードウェアの初期化 target_sau_init(siopid); return p_siopcb; } /* * シリアルクローズ */ void sio_cls_por(SIOPCB *p_siopcb) { /* 送受信禁止 */ // チャネル{0,1}の停止 ST0 |= UINT16_C(0x0003); /* シリアルモジュールを無効にする */ PER0 &= ~TBIT_PER0_SAU0EN; } /* * 1文字送信 */ bool_t sio_snd_chr(SIOPCB *p_siopcb, char c) { // 送信バッファが空ならば,1文字送信 if((SSR00L & TBIT_SSRmnL_TSF) == UINT16_C(0)) { SDR00 = (uint16_t)c; return true; } return false; } /* * 1文字受信 */ int_t sio_rcv_chr(SIOPCB *p_siopcb) { int_t c = -1; // 受信バッファにデータがあれば,1文字受信 if((SSR01L & TBIT_SSRmnL_BFF) != 0) { c = (int_t)SDR01; } return c; } /* * コールバックの許可 */ void sio_ena_cbr(SIOPCB *p_siopcb, uint_t cbrtn) { switch (cbrtn) { case SIO_RDY_SND: p_siopcb->enacb |= TBIT_ENACB_SND; x_clear_int(INTNO_INTST0); ena_int(INTNO_INTST0); break; case SIO_RDY_RCV: p_siopcb->enacb |= TBIT_ENACB_RCV; x_clear_int(INTNO_INTSR0); ena_int(INTNO_INTSR0); break; default: break; } } /* * コールバックの禁止 */ void sio_dis_cbr(SIOPCB *p_siopcb, uint_t cbrtn) { switch (cbrtn) { case SIO_RDY_SND: p_siopcb->enacb &= ~TBIT_ENACB_SND; dis_int(INTNO_INTST0); x_clear_int(INTNO_INTST0); break; case SIO_RDY_RCV: p_siopcb->enacb &= ~TBIT_ENACB_RCV; dis_int(INTNO_INTSR0); x_clear_int(INTNO_INTSR0); break; default: break; } } /* * 割込みサービスルーチン */ /* * 受信割込み */ void sio_isr_rcv(intptr_t portid) { SIOPCB *p_siopcb = GET_SIOPCB((ID)portid); if((p_siopcb->enacb & TBIT_ENACB_RCV) != 0) { /* * 受信通知コールバックルーチンを呼び出す. */ sio_irdy_rcv(p_siopcb->exinf); } } /* * 送信割込み */ void sio_isr_snd(intptr_t portid) { SIOPCB *p_siopcb = GET_SIOPCB((ID)portid); if((p_siopcb->enacb & TBIT_ENACB_SND) != 0) { /* * 送信通知コールバックルーチンを呼び出す. */ sio_irdy_snd(p_siopcb->exinf); } } /* * 1文字出力(ポーリングでの出力) */ void sio_pol_snd_chr(char c, ID siopid) { /* 送信バッファが空になるまで待つ(有限時間内の条件成立を仮定) */ while((SSR00L & TBIT_SSRmnL_TSF) != 0){} // 1文字送信 SDR00 = (uint16_t)c; }