source: rtems/c/src/lib/libcpu/sh/sh7045/sci/sci_termios.c @ c8f3e82

Last change on this file since c8f3e82 was 3a5fec8, checked in by Joel Sherrill <joel.sherrill@…>, on 08/16/01 at 21:50:01

2001-08-10 Radzislaw Galler <rgaller@…>

  • score/cpu_asm.c (sh_set_irq_priority): Changed interrupt vector number range check and handling of interrupt priority regs to conform SH2 specs.
  • sci/sci_termios.c: New file.
  • include/sci_termios.h: New file.
  • include/Makefile.am (EXTRA_DIST): Added sci_termios.h. (include_sh_HEADERS): Added sci_termios.h.
  • score/ispsh7045.c (isp): Calling an ISR with immediate argument casued negative sign extension for vector numbers of 128 and above. This was fixed.
  • sci/sci.c: Cleaned initialization of SCI registers; added necessary setup for new TERMIOS console cooperation
  • Property mode set to 100644
File size: 10.2 KB
Line 
1/*
2 * Termios console serial driver.
3 *
4 * Based on SCI driver by Ralf Corsepius and John M. Mills
5 *
6 * Author: Radzislaw Galler <rgaller@et.put.poznan.pl>
7 *
8 *  COPYRIGHT (c) 1989-2001.
9 *  On-Line Applications Research Corporation (OAR).
10 *
11 *  The license and distribution terms for this file may be
12 *  found in the file LICENSE in this distribution or at
13 *  http://www.OARcorp.com/rtems/license.html.
14 *
15 * $Id$
16 *
17 */
18
19#include <bsp.h>
20#include <stdlib.h>
21
22#include <libchip/serial.h>
23#include <libchip/sersupp.h>
24
25#include <rtems/libio.h>
26#include <iosupp.h>
27
28#include <rtems/score/sh_io.h>
29#include <rtems/score/ispsh7045.h>
30#include <rtems/score/iosh7045.h>
31
32#include <sh/sh7_sci.h>
33#include <sh/sh7_pfc.h>
34#include <sh/sci_termios.h>
35
36
37/*
38 * Some handy macros
39 */
40#define SH_SCI_REG_DATA(_data, _minor, _register) \
41 (write8(_data, Console_Port_Tbl[_minor].ulCtrlPort1 + (_register)))
42
43#define SH_SCI_REG_FLAG(_flag, _minor, _register) \
44 (write8(read8(Console_Port_Tbl[_minor].ulCtrlPort1 + (_register)) | (_flag), \
45         Console_Port_Tbl[_minor].ulCtrlPort1 + (_register)))
46
47#define SH_SCI_REG_MASK(_flag, _minor, _register) \
48 (write8(read8(Console_Port_Tbl[_minor].ulCtrlPort1 + (_register)) & ~(_flag), \
49         Console_Port_Tbl[_minor].ulCtrlPort1 + (_register)))
50
51/*
52 * NOTE: Some SH variants have 3 sci devices
53 */
54 
55#define SCI_MINOR_DEVICES       2
56
57
58/* 
59 * Automatically generated function imported from scitab.rel
60 */
61extern int _sci_get_brparms(
62  tcflag_t      cflag,
63  unsigned char *smr,
64  unsigned char *brr );
65
66/*
67 * Translate termios flags into SCI settings
68 */
69int sh_sci_set_attributes(
70  int minor,
71  const struct termios *t
72)
73{
74    unsigned8   smr ;
75    unsigned8   brr ;
76    int a;
77   
78    tcflag_t c_cflag = t->c_cflag;
79
80    if ( c_cflag & CBAUD )
81    {
82        if ( _sci_get_brparms( c_cflag, &smr, &brr ) != 0 )
83            return -1 ;
84    }
85                   
86    if ( c_cflag & CSIZE )
87    {
88        if ( c_cflag & CS8 )
89            smr &= ~SCI_SEVEN_BIT_DATA;
90        else if ( c_cflag & CS7 )
91            smr |= SCI_SEVEN_BIT_DATA;
92        else
93            return -1 ;
94    }
95
96    if ( c_cflag & CSTOPB )
97        smr |= SCI_STOP_BITS_2;
98    else
99        smr &= ~SCI_STOP_BITS_2;
100
101    if ( c_cflag & PARENB )
102        smr |= SCI_PARITY_ON ;
103    else
104        smr &= ~SCI_PARITY_ON ;
105
106    if ( c_cflag & PARODD )
107        smr |= SCI_ODD_PARITY ;
108    else
109        smr &= ~SCI_ODD_PARITY;
110
111    SH_SCI_REG_MASK((SCI_RE | SCI_TE), minor, SCI_SCR);
112   
113    SH_SCI_REG_DATA(smr, minor, SCI_SMR);
114    SH_SCI_REG_DATA(brr, minor, SCI_BRR);
115   
116    for(a=0; a < 10000L; a++) { /* Delay one bit */
117        asm volatile ("nop");
118    }
119
120    SH_SCI_REG_FLAG((SCI_RE | SCI_TE), minor, SCI_SCR);
121   
122    return 0;
123}
124
125/*
126 * Receive-data-full ISR
127 *
128 * The same routine for all interrupt sources of the same type.
129 */
130rtems_isr sh_sci_rx_isr(rtems_vector_number vector)
131{
132    int minor;
133   
134    for(minor = 0; minor < Console_Port_Count; minor++)
135    {
136        if(Console_Port_Tbl[minor].ulIntVector == vector)
137        {             
138            unsigned8 temp8;
139           
140            /*
141             * FIXME: error handling should be added
142             */
143            temp8 = read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_RDR);
144
145            rtems_termios_enqueue_raw_characters(
146                Console_Port_Data[minor].termios_data,
147                (char*)&temp8, 1);
148
149            SH_SCI_REG_MASK(SCI_RDRF, minor, SCI_SSR);
150            break;
151        }
152    }
153}
154
155/*
156 * Transmit-data-empty ISR
157 *
158 * The same routine for all interrupt sources of the same type.
159 */
160rtems_isr sh_sci_tx_isr(rtems_vector_number vector)
161{
162    int minor;
163
164    for(minor = 0; minor < Console_Port_Count; minor++)
165    {
166        if(Console_Port_Tbl[minor].ulDataPort == vector)
167        {
168            /*
169             * FIXME: Error handling should be added
170             */
171   
172            /*
173             * Mask end-of-transmission interrupt
174             */
175            SH_SCI_REG_MASK(SCI_TIE, minor, SCI_SCR);
176
177            if(rtems_termios_dequeue_characters(
178                   Console_Port_Data[minor].termios_data, 1))
179            {
180                /*
181                 * More characters to be received - interrupt must be enabled
182                 */
183                SH_SCI_REG_FLAG(SCI_TIE, minor, SCI_SCR);
184            }
185            break;
186        }
187    }
188}
189
190
191/*
192 * Initialization of serial port
193 */
194void sh_sci_init(int minor)
195{
196    unsigned16 temp16;
197   
198    /*
199     * set PFC registers to enable I/O pins
200     */
201    if ((minor == 0))
202    {
203        temp16 = read16(PFC_PACRL2);         /* disable SCK0, DMA, IRQ */
204        temp16 &= ~(PA2MD1 | PA2MD0);
205        temp16 |= (PA_TXD0 | PA_RXD0);       /* enable pins for Tx0, Rx0 */
206        write16(temp16, PFC_PACRL2);
207   
208    }
209    else if (minor == 1)
210    { 
211        temp16 = read16(PFC_PACRL2);          /* disable SCK1, DMA, IRQ */
212        temp16 &= ~(PA5MD1 | PA5MD0);
213        temp16 |= (PA_TXD1 | PA_RXD1);        /* enable pins for Tx1, Rx1 */
214        write16(temp16, PFC_PACRL2);
215    }
216
217    /*
218     * Non-default hardware setup occurs in sh_sci_first_open
219     */
220}
221
222/*
223 * Initialization of interrupts
224 *
225 * Interrupts can be started only after opening a device, so interrupt
226 * flags are set up in sh_sci_first_open function
227 */
228void sh_sci_initialize_interrupts(int minor)
229{
230    rtems_isr_entry old_isr;
231    rtems_status_code status;
232
233    sh_sci_init(minor);
234    /*
235     * Disable IRQ of SCIx
236     */
237    status = sh_set_irq_priority(
238        Console_Port_Tbl[minor].ulIntVector, 0);
239
240    if(status != RTEMS_SUCCESSFUL)
241        rtems_fatal_error_occurred(status);
242
243    SH_SCI_REG_MASK(SCI_RIE, minor, SCI_SCR);
244
245    /*
246     * Catch apropriate vectors
247     */
248    status = rtems_interrupt_catch(
249        sh_sci_rx_isr,
250        Console_Port_Tbl[minor].ulIntVector,
251        &old_isr);
252
253    if(status != RTEMS_SUCCESSFUL)
254        rtems_fatal_error_occurred(status);
255
256    status = rtems_interrupt_catch(
257        sh_sci_tx_isr,
258        Console_Port_Tbl[minor].ulDataPort,
259        &old_isr);
260
261    if(status != RTEMS_SUCCESSFUL)
262        rtems_fatal_error_occurred(status);
263   
264    /*
265     * Enable IRQ of SCIx
266     */
267    SH_SCI_REG_FLAG(SCI_RIE, minor, SCI_SCR);
268
269    status = sh_set_irq_priority(
270        Console_Port_Tbl[minor].ulIntVector,
271        Console_Port_Tbl[minor].ulCtrlPort2);
272
273    if(status != RTEMS_SUCCESSFUL)
274        rtems_fatal_error_occurred(status);
275}
276
277
278/*
279 *  Open entry point
280 *   Sets up port and pins for selected sci.
281 */
282
283int sh_sci_first_open(
284  int major,
285  int minor,
286  void *arg )
287{
288    unsigned8 temp8;
289    unsigned int a ;
290 
291    /*
292     * check for valid minor number
293     */
294    if(( minor > ( SCI_MINOR_DEVICES -1 )) || ( minor < 0 ))
295    {
296        return RTEMS_INVALID_NUMBER;
297    }
298
299    /*
300     * set up SCI registers
301     */
302    /* Clear SCR - disable Tx and Rx */
303    SH_SCI_REG_DATA(0x00, minor, SCI_SCR);
304   
305    /* set SMR and BRR - baudrate and format */
306    sh_sci_set_attributes(minor, Console_Port_Tbl[minor].pDeviceParams);
307
308    for(a=0; a < 10000L; a++) {                      /* Delay */
309        asm volatile ("nop");
310    }
311
312    write8((SCI_RE | SCI_TE),              /* enable async. Tx and Rx */
313           Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SCR);
314
315    /*
316     * clear error flags
317     */
318    temp8 = read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SSR);
319    while(temp8 & (SCI_RDRF | SCI_ORER | SCI_FER | SCI_PER))
320    {
321        /* flush input */
322        temp8 = read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_RDR);
323
324        /* clear some flags */
325        SH_SCI_REG_FLAG((SCI_RDRF | SCI_ORER | SCI_FER | SCI_PER), minor, SCI_SSR);
326       
327        /* check if everything is OK */
328        temp8 = read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SSR);
329    }   
330   
331    /* Clear RDRF flag */
332    SH_SCI_REG_DATA(0x00, minor, SCI_TDR); /* force output */
333   
334    /* Clear the TDRE bit */
335    SH_SCI_REG_FLAG(SCI_TDRE, minor, SCI_SSR);
336   
337    /*
338     * Interrupt setup
339     */
340    if(Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts)
341    {
342        SH_SCI_REG_FLAG(SCI_RIE, minor, SCI_SCR);
343    }
344   
345    return RTEMS_SUCCESSFUL ;
346}
347
348/*
349 *  Close entry point
350 */
351
352int sh_sci_last_close(
353  int major,
354  int minor,
355  void *arg
356)
357{
358    /* FIXME: Incomplete */
359
360    /* Shutdown interrupts if necessary */
361    if(Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts)
362    {
363        SH_SCI_REG_MASK((SCI_TIE | SCI_RIE), minor, SCI_SCR);
364    }
365    return RTEMS_SUCCESSFUL ;
366}
367
368/*
369 * Interrupt aware write routine
370 */
371int sh_sci_write_support_int(
372    int         minor,
373    const char *buf,
374    int         len
375)
376{
377    if(!len)
378        return 0;
379    /*
380     * Put data into TDR and clear transmission-end-flag
381     */
382    SH_SCI_REG_DATA(*buf, minor, SCI_TDR);
383    SH_SCI_REG_MASK(SCI_TDRE, minor, SCI_SSR);
384    /* 
385     * Enable interrupt
386     */
387    SH_SCI_REG_FLAG(SCI_TIE, minor, SCI_SCR);
388   
389    return 1;
390}
391
392/*
393 * Polled write method
394 */
395int sh_sci_write_support_polled(
396  int   minor,
397  const char *buf,
398  int   len
399)
400{
401    int count = 0;
402   
403    while(count < len)
404    {
405        sh_sci_write_polled(minor, buf[count]);
406        count++;
407    }
408    /*
409     * Return number of bytes written
410     */
411    return count;
412}
413
414/*
415 * Polled write of one character at a time
416 */
417void sh_sci_write_polled(
418    int minor,
419    char c
420)
421{
422    /*
423     * Wait for end of previous character
424     */
425    while(!(read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SSR) & SCI_TDRE));
426    /*
427     * Send the character
428     */
429    SH_SCI_REG_DATA(c, minor, SCI_TDR);
430   
431    /*
432     * Clear TDRE flag
433     */
434    SH_SCI_REG_MASK(SCI_TDRE, minor, SCI_SSR);
435}
436
437/*
438 * Non-blocking read
439 */
440int sh_sci_inbyte_nonblocking_polled(int minor)
441{
442    unsigned8 inbyte;
443
444    /*
445     * Check if input buffer is full
446     */
447    if(read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SSR) & SCI_RDRF)
448    {
449        inbyte = read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_RDR);
450        SH_SCI_REG_MASK(SCI_RDRF, minor, SCI_SSR);
451       
452        /*
453         * Check for errors
454         */
455        if(read8(Console_Port_Tbl[minor].ulCtrlPort1 + SCI_SSR) &
456           (SCI_ORER | SCI_FER | SCI_PER))
457        {
458            SH_SCI_REG_MASK((SCI_ORER | SCI_FER | SCI_PER), minor, SCI_SSR);
459            return -1;
460        }     
461        return (int)inbyte;
462    }
463    return -1;
464}
Note: See TracBrowser for help on using the repository browser.