1 /*******************************************************************
2 Components for embedded applications builded for
3 laboratory and medical instruments firmware
5 qsm_rs232.c - 683xx QSM module RS-232 communication implementation
7 Copyright (C) 2001-2003 by Pavel Pisa pisa@cmp.felk.cvut.cz
8 (C) 2001-2003 by PiKRON Ltd. http://www.pikron.com
10 *******************************************************************/
13 #include <system_def.h>
16 #include <periph/qsm_rs232.h>
18 #define QSM_CHAR_XON 0x11
19 #define QSM_CHAR_XOFF 0x13
21 #define QSM_RS232_RTS_PEM (1<<0)
22 #define QSM_RS232_CTS_PEM (1<<1)
24 #define qsm_rs232_rts_true() \
25 atomic_set_mask_b(QSM_RS232_RTS_PEM,SIM_PORTE0)
26 #define qsm_rs232_rts_false() \
27 atomic_clear_mask_b(QSM_RS232_RTS_PEM,SIM_PORTE0)
28 #define qsm_rs232_cts() (!(*SIM_PORTE0&QSM_RS232_CTS_PEM))
30 int qsm_rs232_baud=9600;
31 int qsm_rs232_mode=QSM_RS232_MODEA;
32 int qsm_rs232_flowc=1;
33 #define QSM_RSFLC_HW 0x1
34 #define QSM_RSFLC_XON 0x2
36 typedef volatile struct{
43 #define QSM_RS232_BUF_LEN (80*8)
44 #define QSM_RS232_BUF_FULLTG (84)
46 qsm_que_t qsm_rs232_que_in; /* input qureue */
47 uint8_t qsm_rs232_buf_in[QSM_RS232_BUF_LEN];
49 qsm_que_t qsm_rs232_que_out; /* output queue */
50 uint8_t qsm_rs232_buf_out[QSM_RS232_BUF_LEN];
52 short qsm_rs232_flags;
53 #define QSM_RSFL_ROR 0x1
54 #define QSM_RSFL_RFE 0x2
55 #define QSM_RSFL_RPE 0x4
56 #define QSM_RSFL_SXOFF 0x10
57 #define QSM_RSFL_SXON 0x20
58 #define QSM_RSFL_TFCDI 0x40
59 #define QSM_RSFL_RFCDI 0x80
60 #define QSM_RSFL_TIP 0x100
61 #define QSM_RSFL_TWCTS 0x200
63 int qsm_rs232_irq_cnt;
66 /* put character c into queue, if full return -1 */
67 int qsm_que_put(qsm_que_t *q, int c)
72 if(p==q->buf_end) p=q->buf_beg;
73 if(p==q->op) return -1;
78 /* get character from queue, if empty return -1 */
79 int qsm_que_get(qsm_que_t *q)
84 if(p==q->ip) return -1;
86 if(p==q->buf_end) p=q->buf_beg;
91 int qsm_que_freecnt(qsm_que_t *q)
93 uint8_t *ip=q->ip,*op=q->op;
94 return op-ip-1+(op<=ip?q->buf_end-q->buf_beg:0);
97 int qsm_que_incnt(qsm_que_t *q)
99 uint8_t *ip=q->ip,*op=q->op;
100 return ip-op+(ip<op?q->buf_end-q->buf_beg:0);
104 void putDebugChar(int ch) /* write a single character */
106 while(!(*QSM_SCSR&QSM_TDRE)) ;
110 int getDebugChar(void) /* read and return a single char */
112 while(!(*QSM_SCSR&QSM_RDRF)) ;
116 extern void qsm_rs232_gdb_isr();
120 "qsm_rs232_gdb_isr:\n\t"
121 /* emulate vector 31 SIGINT - unix signal number 2 */
122 "movew #0x7c,%sp@(6)\n\t"
124 "movel %a0,%sp@-\n\t"
126 /* redirect to the vector 31 */
127 "movel %a0@(0x7c),%a0\n\t"
128 "movel %a0,%sp@(4)\n\t"
129 "movel %sp@+,%a0\n\t"
133 void qsm_used4gdbdirect(void)
136 /* only receive interrupt is used */
137 atomic_clear_mask_w(QSM_TIE|QSM_ILIE,QSM_SCCR1);
139 vbr[ISR_QSM_INTV]=qsm_rs232_gdb_isr;
142 #endif /* WITH_GDBSTUB */
145 void qsm_rs232_isr(int intno, void *dev_id, struct pt_regs *regs)
157 scsrdr.srdr=*(volatile uint32_t*)QSM_SCSR;
158 if(scsrdr.s.sr&QSM_RDRF){
159 /* character received */
162 if((qsm_break2gdb&&(scsrdr.s.dr==0x3))||qsm_used4gdbonly){
163 /* ctrl+c received or GDB-only set */
164 /* initiate exception 31 equal to */
165 /* SIGINT - unix signal number 2 */;
166 regs->vector=4*31; /* emulated SIGINT vector */
167 irq_redirect2vector(31,regs);
170 #endif /* WITH_GDBSTUB */
171 if(scsrdr.s.sr&(QSM_OR|QSM_FE|QSM_PE)){
172 if(scsrdr.s.sr&QSM_OR)qsm_rs232_flags|=QSM_RSFL_ROR;
173 if(scsrdr.s.sr&QSM_FE)qsm_rs232_flags|=QSM_RSFL_RFE;
174 if(scsrdr.s.sr&QSM_PE)qsm_rs232_flags|=QSM_RSFL_RPE;
177 if(qsm_rs232_flowc&QSM_RSFLC_XON){
178 if(scsrdr.s.dr==QSM_CHAR_XON){
179 qsm_rs232_flags&=~QSM_RSFL_TFCDI;
181 }else if(scsrdr.s.dr==QSM_CHAR_XOFF){
182 qsm_rs232_flags|=QSM_RSFL_TFCDI;
186 if(qsm_que_put(&qsm_rs232_que_in,scsrdr.s.dr)<0)
187 qsm_rs232_flags|=QSM_RSFL_ROR;
188 if((!(qsm_rs232_flags&QSM_RSFL_RFCDI))&&
189 (qsm_que_freecnt(&qsm_rs232_que_in)<=QSM_RS232_BUF_FULLTG)){
190 qsm_rs232_flags|=QSM_RSFL_RFCDI;
191 if(qsm_rs232_flowc&QSM_RSFLC_XON){
192 qsm_rs232_flags&=~QSM_RSFL_SXON;
193 qsm_rs232_flags|=QSM_RSFL_SXOFF;
195 if(qsm_rs232_flowc&QSM_RSFLC_HW) qsm_rs232_rts_false();
200 if(scsrdr.s.sr&QSM_TDRE){
201 atomic_clear_mask_w(QSM_TIE,QSM_SCCR1);
203 if(qsm_used4gdbonly) {
206 #endif /* WITH_GDBSTUB*/
207 qsm_rs232_flags&=~QSM_RSFL_TIP;
208 if(!(qsm_rs232_flowc&QSM_RSFLC_HW)||qsm_rs232_cts()){
209 qsm_rs232_flowc&=~QSM_RSFL_TWCTS;
210 if(qsm_rs232_flags&(QSM_RSFL_SXON|QSM_RSFL_SXOFF)){
211 val=qsm_rs232_flags&QSM_RSFL_SXON?QSM_CHAR_XON:QSM_CHAR_XOFF;
212 qsm_rs232_flags&=~(QSM_RSFL_SXON|QSM_RSFL_SXOFF);
213 qsm_rs232_flags|=QSM_RSFL_TIP;
215 atomic_set_mask_w(QSM_TIE,QSM_SCCR1);
217 if(!(qsm_rs232_flags&QSM_RSFL_TFCDI)){
218 if((val=qsm_que_get(&qsm_rs232_que_out))>=0){
219 qsm_rs232_flags|=QSM_RSFL_TIP;
221 atomic_set_mask_w(QSM_TIE,QSM_SCCR1);
226 qsm_rs232_flowc|=QSM_RSFL_TWCTS;
230 int qsm_rs232_sendch(int c)
232 if(qsm_que_put(&qsm_rs232_que_out,c)<0){
233 if((qsm_rs232_flags&QSM_RSFL_TWCTS)&&qsm_rs232_cts())
234 atomic_set_mask_w(QSM_TIE,QSM_SCCR1);
237 if(qsm_rs232_flags&QSM_RSFL_TIP) return c;
238 if(qsm_rs232_flags&QSM_RSFL_TFCDI) return c;
239 if((qsm_rs232_flowc&QSM_RSFLC_HW)&&!qsm_rs232_cts()){
241 qsm_rs232_flags|=QSM_RSFL_TWCTS;
245 atomic_set_mask_w(QSM_TIE,QSM_SCCR1);
249 int qsm_rs232_recch()
252 if((qsm_rs232_flags&QSM_RSFL_TWCTS)&&qsm_rs232_cts())
253 atomic_set_mask_w(QSM_TIE,QSM_SCCR1);
254 val=qsm_que_get(&qsm_rs232_que_in);
255 if(qsm_rs232_flags&QSM_RSFL_RFCDI)
257 if(qsm_que_freecnt(&qsm_rs232_que_in)>=QSM_RS232_BUF_FULLTG+8)
259 if(qsm_rs232_flowc&QSM_RSFLC_HW)
260 qsm_rs232_rts_true();
262 qsm_rs232_flags&=~QSM_RSFL_RFCDI;
269 int qsm_rs232_sendstr(const char *s)
274 if(qsm_rs232_sendch((unsigned char)(*(s++)))<0) break;
285 restore_flags(flags);
288 irq_handler_t qsm_rs232_handler={
289 handler: qsm_rs232_isr,
292 devname: "qsm_rs232",
297 int qsm_rs232_setmode(int baud, int mode, int flowc)
299 if(baud==-1) baud=qsm_rs232_baud;
300 if(mode==-1) mode=qsm_rs232_mode;
301 if(flowc==-1) flowc=qsm_rs232_flowc;
303 atomic_clear_mask_w(QSM_RIE|QSM_TIE|QSM_TCIE|QSM_ILIE,QSM_SCCR1);
308 *QSM_SCCR0=(cpu_sys_hz+baud/2)/baud; /* SCBR */
311 qsm_rs232_flowc=flowc;
318 qsm_rs232_que_in.buf_beg=qsm_rs232_buf_in;
319 qsm_rs232_que_in.buf_end=qsm_rs232_que_in.buf_beg+sizeof(qsm_rs232_buf_in);
320 qsm_rs232_que_in.ip=qsm_rs232_que_in.buf_beg;
321 qsm_rs232_que_in.op=qsm_rs232_que_in.buf_beg;
323 qsm_rs232_que_out.buf_beg=qsm_rs232_buf_out;
324 qsm_rs232_que_out.buf_end=qsm_rs232_que_out.buf_beg+sizeof(qsm_rs232_buf_out);
325 qsm_rs232_que_out.ip=qsm_rs232_que_out.buf_beg;
326 qsm_rs232_que_out.op=qsm_rs232_que_out.buf_beg;
328 if(qsm_rs232_flowc&QSM_RSFLC_HW){
329 *SIM_DDRE|=QSM_RS232_RTS_PEM;
330 *SIM_DDRE&=~QSM_RS232_CTS_PEM;
331 *SIM_PEPAR&=~(QSM_RS232_CTS_PEM|QSM_RS232_RTS_PEM);
332 qsm_rs232_rts_true();
336 *QSM_CR&=~(QSM_STOP|(QSM_IARB^ISR_QSM_IARB));
337 *QSM_CR|=ISR_QSM_IARB;
338 *QSM_QILR&=~QSM_ILSCI;
339 *QSM_QIVR=ISR_QSM_INTV;
340 *QSM_QILR|=ISR_QSM_ILSCI;
342 if(test_irq_handler(ISR_QSM_INTV,&qsm_rs232_handler)==0)
343 add_irq_handler(ISR_QSM_INTV,&qsm_rs232_handler);
345 atomic_set_mask_w(QSM_RIE,QSM_SCCR1);