📄 sh-sci.c
字号:
/* sh-sci.c: SCIF functions for SH7750 * * Copyright (C) 2001 KOMORIYA Takeru * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the file "GPL" for more details. * * Contact to author: * KOMORIYA Takeru, AAF Sendai Lab., Japan * E-mail: komoriya@chmodx.dyndns.org * URL: http://chmodx.dyndns.org/aaf/ */#include "sh7750.h"#include "sh-intr.h"/* Ring buffer size */#define RING_SIZE 1024 /* must be 2^n *//* Tramsmit trigger note: value must be 8/4/2/1 SCFSR2.TTRG must be set correctly. */#define TX_TRIGGER 4struct ring_buffer{ volatile unsigned char buf[RING_SIZE]; volatile unsigned int head; volatile unsigned int tail;};static struct ring_buffer ring_tx, ring_rx;/* send data to SCIF FIFO */static voidscif_tx (void){ unsigned short fifo_num; int i; /* Check if tx-fifo is empty */ if (!(SCFSR2 & 0x0020)) /* SCFSR2.TDFE */ return; /* not empty */ if (ring_tx.head == ring_tx.tail) /* no data in ring buffer */ { SCSCR2 = SCSCR2 & ~0x0080; /* Clear SCSCR2.TIE */ return; } /* send to FIFO */ for (i=0; i< 16 - TX_TRIGGER; i++) { if (ring_tx.head == ring_tx.tail) break; SCFTDR2 = ring_tx.buf[ring_tx.head]; ring_tx.head++; ring_tx.head &= RING_SIZE - 1; } /* Clear SCFSR2.TEND */ SCFSR2 = SCFSR2 & ~0x0040; /* How many data in Tx-FIFO? */ fifo_num = SCFDR2 & 0x1f00; fifo_num >>= 8; if (fifo_num > TX_TRIGGER) SCFSR2 = SCFSR2 & ~0x0020; /* Clear SCFSR2.TDFE */}/* receive data from SCIF FIFO */static voidscif_rx (void){ int i, is_err; unsigned int p; unsigned short scfsr; unsigned short fifo_num; unsigned char fifo_data; is_err = 0; if (SCLSR2 & 0x0001) /* SCLSR2.ORER */ { /* SCI-FIFO overrun error */ is_err = 1; } scfsr = SCFSR2; if (scfsr & 0x0080) /* SCFSR2.ER */ { /* Framing error / Parity error */ is_err = 1; } if (scfsr & 0x0010) /* SCFSR2.BRK */ { /* break detect */ is_err = 1; } if (scfsr & 0x0003) /* SCFSR2.RDF | SCFSR2.DR */ { /* receive from FIFO */ fifo_num = SCFDR2 & 0x001f; for (i=0; i<fifo_num; i++) { fifo_data = SCFRDR2; p = ring_rx.tail + 1; p &= RING_SIZE - 1; if (p == ring_rx.head) /* ring buffer overflow! */ continue; ring_rx.buf[ring_rx.tail] = fifo_data; ring_rx.tail = p; } if (scfsr & 0x0002) /* SCFSR2.RDF */ SCFSR2 = SCFSR2 & ~0x0002; /* RDF = 0 */ if (scfsr & 0x0001) /* SCFSR2.DR */ is_err = 1; } if (is_err) { SCLSR2 = SCLSR2 & ~0x0001; /* ORER = 0 */ SCFSR2 = SCFSR2 & ~0x0091; /* DR = ER = BRK = 0 */ }}/* handle receive error interrupt */static voidscif_error (void){ if (SCFSR2 & 0x0080) /* SCFSR2.ER */ { /* Framing error / Parity error */ SCFSR2 = SCFSR2 & ~0x0080; }}/* handle break interrupt */static voidscif_break (void){ if (SCFSR2 & 0x0010) /* SCFSR2.BRK */ { /* break detect */ SCFSR2 = SCFSR2 & ~0x0010; } if (SCLSR2 & 0x0001) /* SCLSR2.ORER */ { /* SCI-FIFO overrun error */ SCLSR2 = SCLSR2 & ~0x0001; }}/* SCIF initialize */voidscif_init(void){ intr_disable(); /* Initialize ring buffer */ ring_tx.head = 0; ring_tx.tail = 0; ring_rx.head = 0; ring_rx.tail = 0; SCSCR2 = 0x0000; /* TE=0, RE=0, CKE1=0 */ SCFCR2 = 0x0006; /* TFRST=1, RFRST=1 */ SCSMR2 = 0x0000; /* CHR=0, PE=0, STOP=0, CKS=00 */ /* 8-bit, non-parity, 1 stop bit, pf/1 clock */ SCBRR2 = 6; /* Baudrate setting 6: 115200 bps */ RFCR = 0xa400; /* Refresh counter clear */ while(RFCR < 500) ; SCSPTR2 = 0x0080; /* Set RTS = 1 */ SCFCR2 = 0x0090; /* RTRG=10,TTRG=01,MCE=0,TFRST=0,RFRST=0,LOOP=0 Note: 'TX_TRIGGER' depends on TTRG */ /* register interrupt handler */ intr_register (INTR_SCIF_TXI, scif_tx); intr_register (INTR_SCIF_RXI, scif_rx); intr_register (INTR_SCIF_ERI, scif_error); intr_register (INTR_SCIF_BRI, scif_break); /* set interrupt priority for SCIF */ intr_set_priority (MOD_SCIF, 8); SCSCR2 = 0x0078; /* TIE=0,RIE=1,REIE=1,TE=1,RE=1 */ intr_enable();}/* Get char (non-blocking) */intscif_getc (void){ unsigned char d; if (ring_rx.head == ring_rx.tail) return -1; intr_disable(); d = ring_rx.buf[ring_rx.head]; ring_rx.head++; ring_rx.head &= RING_SIZE - 1; intr_enable(); return (int)d;}/* Get char with waiting */intscif_getcw (void){ unsigned char d; while (ring_rx.head == ring_rx.tail) ; intr_disable(); d = ring_rx.buf[ring_rx.head]; ring_rx.head++; ring_rx.head &= RING_SIZE - 1; intr_enable(); return (int)d;}/* Put char */intscif_putc (unsigned char ch){ unsigned int p; intr_disable(); p = ring_tx.tail + 1; p &= RING_SIZE - 1; if (p == ring_tx.head) { intr_enable(); return -1; } ring_tx.buf[ring_tx.tail] = ch; ring_tx.tail = p; SCSCR2 = SCSCR2 | 0x0080; /* Set SCSCR2.TIE to invoke scif_tx */ intr_enable(); return 0;}/* Put string */intscif_puts (const char *s){ unsigned int p; intr_disable(); while(*s) { p = ring_tx.tail + 1; p &= RING_SIZE - 1; if (p == ring_tx.head) { SCSCR2 = SCSCR2 | 0x0080; /* Set SCSCR2.TIE to invoke scif_tx */ intr_enable(); return -1; } ring_tx.buf[ring_tx.tail] = *s; ring_tx.tail = p; s++; } SCSCR2 = SCSCR2 | 0x0080; /* Set SCSCR2.TIE to invoke scif_tx */ intr_enable(); return 0;}/* Flush transmit ring buffer */voidscif_flush (void){ while (ring_tx.head != ring_tx.tail) ; /* Check SCFSR2.TEND */ while (!(SCFSR2 & 0x0040)) ;}/* Disable SCIF */voidscif_disable (void){ scif_flush(); SCSCR2 = 0x0000; /* TE=0, RE=0, CKE1=0 */ intr_unregister (INTR_SCIF_TXI); intr_unregister (INTR_SCIF_RXI); intr_unregister (INTR_SCIF_ERI); intr_unregister (INTR_SCIF_BRI);}/* Put decimal digit to SCI */voidscif_put_decimal (long a){ char c[12]; int i, j, pm; i = 0; pm = 0; if (a < 0) { pm = 1; a = -a; } if (a == 0) { c[0] = '0'; i = 1; } while (a > 0) { c[i] = '0' + a % 10; a /= 10; i++; } if (pm) c[i] = '-'; else i--; for (j=i; j>=0; j--) scif_putc (c[j]);}/* Put hex to SCI */voidscif_put_hex (unsigned long a, int digit){ char c[8]; int b, i, j; i = 0; for (i=0; i<digit; i++) { b = a & 0x0f; if (b < 0x0a) c[i] = '0' + b; else c[i] = 'a' + b - 0x0a; a >>= 4; } for (j=digit-1; j>=0; j--) scif_putc (c[j]);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -