h8s_sci.c

Go to the documentation of this file.
00001 //=============================================================================
00002 //
00003 //      h8s_sci.c
00004 //
00005 //      Simple driver for the H8S Serial Communication Interface (SCI)
00006 //      for diagnostic serial communication.
00007 //
00008 //=============================================================================
00009 //####ECOSGPLCOPYRIGHTBEGIN####
00010 // -------------------------------------------
00011 // This file is part of eCos, the Embedded Configurable Operating System.
00012 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
00013 //
00014 // eCos is free software; you can redistribute it and/or modify it under
00015 // the terms of the GNU General Public License as published by the Free
00016 // Software Foundation; either version 2 or (at your option) any later version.
00017 //
00018 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
00019 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
00020 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00021 // for more details.
00022 //
00023 // You should have received a copy of the GNU General Public License along
00024 // with eCos; if not, write to the Free Software Foundation, Inc.,
00025 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00026 //
00027 // As a special exception, if other files instantiate templates or use macros
00028 // or inline functions from this file, or you compile this file and link it
00029 // with other works to produce a work based on this file, this file does not
00030 // by itself cause the resulting work to be covered by the GNU General Public
00031 // License. However the source code for this file must still be made available
00032 // in accordance with section (3) of the GNU General Public License.
00033 //
00034 // This exception does not invalidate any other reasons why a work based on
00035 // this file might be covered by the GNU General Public License.
00036 //
00037 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
00038 // at http://sources.redhat.com/ecos/ecos-license/
00039 // -------------------------------------------
00040 //####ECOSGPLCOPYRIGHTEND####
00041 //=============================================================================
00042 //#####DESCRIPTIONBEGIN####
00043 //
00044 // Author(s):   ysato
00045 // Contributors:ysato, Uwe Kindler
00046 // Date:        2003-12-06
00047 // Description: Simple driver for the H8S Serial Communication Interface. The 
00048 //              SCI is the same for all H8S variants so we define this here in
00049 //              architecture hal
00050 //
00051 //####DESCRIPTIONEND####
00052 //
00053 //=============================================================================
00054 
00055 
00056 //=============================================================================
00057 //                            DOXYGEN FILE HEADER
00065 //=============================================================================
00066 
00067 
00068 //=============================================================================
00069 //                                 INCLUDES
00070 //=============================================================================
00071 #include <pkgconf/hal.h>
00072 
00073 #include <cyg/hal/hal_io.h>             // IO macros
00074 #include <cyg/hal/hal_misc.h>           // Helper functions
00075 #include <cyg/hal/hal_intr.h>           // HAL_ENABLE/MASK/UNMASK_INTERRUPTS
00076 #include <cyg/hal/hal_arch.h>           // SAVE/RESTORE GP
00077 #include <cyg/hal/hal_if.h>             // Calling-if API
00078 #include <cyg/hal/mod_regs_sci.h>       // serial register definitions
00079 
00080 #include <cyg/hal/h8s_sci.h>            // our header
00081 
00082 //
00083 // if the kernel is present then also the kernel API have to be present
00084 // in order to use driver api
00085 //
00086 #if !defined(CYGPKG_KERNEL) || defined(CYGFUN_KERNEL_API_C) 
00087 #include <cyg/hal/drv_api.h>            // CYG_ISR_HANDLED
00088 #endif
00089 
00090 
00091 //=============================================================================
00092 //                            INITIALIZE SCI CHANNEL
00100 //=============================================================================
00101 void hal_sci_init_channel(void* chan)
00102 {
00103     cyg_uint8  tmp;
00104     cyg_uint8 *base = ((channel_data_t *)chan)->base;
00105 
00106     //
00107     // Disable Tx/Rx interrupts, but enable Tx/Rx. Set 8-1-no parity an
00108     // Set speed to value stored in chan->baud_rate
00109     //
00110     HAL_WRITE_UINT8(base + _REG_SCSCR, CYGARC_REG_SCSCR_TE | CYGARC_REG_SCSCR_RE);
00111     HAL_WRITE_UINT8(base + _REG_SCSMR, 0);                           // 8-1-no parity.
00112     HAL_READ_UINT8(base + _REG_SCSMR, tmp);                          // now set baud rate
00113     tmp &= ~CYGARC_REG_SCSMR_CKSx_MASK;
00114     tmp |= CYGARC_SCBRR_CKSx(((channel_data_t *)chan)->baud_rate);
00115     HAL_WRITE_UINT8(base + _REG_SCSMR, tmp);
00116     HAL_WRITE_UINT8(base + _REG_SCBRR, CYGARC_SCBRR_N(((channel_data_t *)chan)->baud_rate));   
00117 }
00118 
00119 
00120 //=============================================================================
00121 //                         READ CHARACTER NONBLOCKED
00122 //
00132 //=============================================================================
00133 static cyg_bool hal_sci_getc_nonblock(void* __ch_data, cyg_uint8* ch)
00134 {
00135     cyg_uint8 *base = ((channel_data_t*)__ch_data)->base;
00136     cyg_uint8  sr;
00137 
00138     HAL_READ_UINT8(base+ _REG_SCSSR, sr);
00139     //
00140     // check if we have an RX overrun
00141     //
00142     if (sr & CYGARC_REG_SCSSR_ORER) 
00143     {
00144         //
00145         // Serial RX overrun. Clear error and let caller try again.
00146         //
00147         HAL_WRITE_UINT8(base + _REG_SCSSR, 
00148                         CYGARC_REG_SCSSR_CLEARMASK & ~CYGARC_REG_SCSSR_ORER);
00149         return false;
00150     }
00151     //
00152     // if no char arrived leave immediatelly with false
00153     //
00154     if ((sr & CYGARC_REG_SCSSR_RDRF) == 0)
00155     {
00156         return false;
00157     }
00158     //
00159     // read the received char and clear buffer full flag
00160     //
00161     HAL_READ_UINT8(base+_REG_SCRDR, *ch);
00162     HAL_WRITE_UINT8(base+_REG_SCSSR, sr & ~CYGARC_REG_SCSSR_RDRF);     // Clear buffer full flag
00163 
00164     return true;
00165 }
00166 
00167 
00168 //=============================================================================
00169 //                           POLL FOR CHARACTER
00175 //=============================================================================
00176 cyg_uint8 hal_sci_getc(void *__ch_data)
00177 {
00178     cyg_uint8 ch;
00179     CYGARC_HAL_SAVE_GP();
00180 
00181     while(!hal_sci_getc_nonblock(__ch_data, &ch))
00182     {
00183         // do nothing
00184     }
00185 
00186     CYGARC_HAL_RESTORE_GP();
00187     return ch;
00188 }
00189 
00190 
00191 //=============================================================================
00192 //                           WRITE CHARACTER
00202 //=============================================================================
00203 void hal_sci_putc(void *__ch_data, cyg_uint8 c)
00204 {
00205     cyg_uint8 *base = ((channel_data_t*)__ch_data)->base;
00206     cyg_uint8  sr;
00207 
00208 
00209     CYGARC_HAL_SAVE_GP();
00210     //
00211     // wait until send register is empty
00212     //
00213     do 
00214     {
00215         HAL_READ_UINT8(base + _REG_SCSSR, sr);
00216     } 
00217     while ((sr & CYGARC_REG_SCSSR_TDRE) == 0);
00218     //
00219     // Write char into send register and clear the empty flag
00220     //
00221     HAL_WRITE_UINT8(base + _REG_SCTDR, c);
00222     HAL_WRITE_UINT8(base + _REG_SCSSR, sr & ~CYGARC_REG_SCSSR_TDRE); // Clear empty flag.
00223     //
00224     // Hang around until the character has been safely sent.
00225     //
00226     do 
00227     {
00228         HAL_READ_UINT8(base + _REG_SCSSR, sr);
00229     } 
00230     while ((sr & CYGARC_REG_SCSSR_TDRE) == 0);
00231 
00232     CYGARC_HAL_RESTORE_GP();
00233 }
00234 
00235 //
00236 // If we use virtual vector table then we have to define some additional
00237 // functions for the COMM tables within the virtual vector table
00238 //
00239 #if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG)
00240 
00241 //=============================================================================
00242 //                          WRITE BUFFER OF CHARACTERS
00250 //=============================================================================
00251 void hal_sci_write(void            *__ch_data, 
00252                    const cyg_uint8 *__buf, 
00253                    cyg_uint32       __len)
00254 {
00255     CYGARC_HAL_SAVE_GP();
00256     //
00257     // Send buffer until detection of terminating zero
00258     //
00259     while(__len-- > 0)
00260     {
00261         hal_sci_putc(__ch_data, *__buf++);
00262     }
00263 
00264     CYGARC_HAL_RESTORE_GP();
00265 }
00266 
00267 
00268 
00269 //=============================================================================
00270 //                          READ BUFFER OF CHARACTERS
00279 //=============================================================================
00280 void hal_sci_read(void      *__ch_data, 
00281                   cyg_uint8 *__buf, 
00282                   cyg_uint32 __len)
00283 {
00284     CYGARC_HAL_SAVE_GP();
00285     //
00286     // Read a number of chars from SCI until __len ist counted down
00287     // to zero
00288     //
00289     while(__len-- > 0)
00290     {
00291         *__buf++ = hal_sci_getc(__ch_data);
00292     }
00293 
00294     CYGARC_HAL_RESTORE_GP();
00295 }
00296 
00297 
00298 //=============================================================================
00299 //                       READ CHARACTER WITH TIMEOUT
00307 //=============================================================================
00308 cyg_bool hal_sci_getc_timeout(void *__ch_data, cyg_uint8 *ch)
00309 {
00310     channel_data_t *chan = (channel_data_t*)__ch_data;
00311     int            delay_count;
00312     cyg_bool       res;
00313 
00314 
00315     CYGARC_HAL_SAVE_GP();
00316 
00317     delay_count = chan->msec_timeout * 20; // delay in .1 ms steps 
00318     //
00319     // Loop until we received a char or until time is over
00320     //
00321     while (1)
00322     {
00323         res = hal_sci_getc_nonblock(__ch_data, ch);
00324         if (res || (0 == delay_count--))
00325         {
00326             break;
00327         }
00328         
00329         CYGACC_CALL_IF_DELAY_US(50);
00330     }
00331 
00332     CYGARC_HAL_RESTORE_GP();
00333     return res;
00334 }
00335 
00336 
00337 //=============================================================================
00338 //                          CONTROL SCI DEVICE
00355 //=============================================================================
00356 int hal_sci_control(void *__ch_data, __comm_control_cmd_t __func, ...)
00357 {
00358     channel_data_t *chan      = (channel_data_t*)__ch_data;
00359     cyg_uint8       scr;
00360     int             ret       = 0;
00361     
00362     
00363     CYGARC_HAL_SAVE_GP();
00364     //
00365     // decide what we have to do according to the control command
00366     //
00367     switch (__func) 
00368     {
00369         //
00370         // Enable receive interrupts
00371         //
00372         case __COMMCTL_IRQ_ENABLE:
00373              HAL_READ_UINT8(chan->base+_REG_SCSCR, scr);
00374              scr |= CYGARC_REG_SCSCR_RIE;
00375              HAL_WRITE_UINT8(chan->base+_REG_SCSCR, scr);
00376              break;
00377         //
00378         // disable receive interrupts
00379         //
00380         case __COMMCTL_IRQ_DISABLE:
00381              HAL_READ_UINT8(chan->base+_REG_SCSCR, scr);
00382              scr &= ~CYGARC_REG_SCSCR_RIE;
00383              HAL_WRITE_UINT8(chan->base+_REG_SCSCR, scr);
00384              break;
00385         //
00386         // query isr vector of channel
00387         //
00388         case __COMMCTL_DBG_ISR_VECTOR:
00389              ret = chan->isr_vector;
00390              break;
00391         //
00392         // set new timeout and return the old one
00393         //
00394         case __COMMCTL_SET_TIMEOUT:
00395              {
00396                  va_list ap;
00397 
00398                  va_start(ap, __func);
00399 
00400                  ret = chan->msec_timeout;
00401                  chan->msec_timeout = va_arg(ap, cyg_uint32);
00402 
00403                  va_end(ap);
00404              } 
00405              break;
00406         //
00407         // set new baudrate for comm channel
00408         // 
00409         case __COMMCTL_SETBAUD:
00410              {
00411                 cyg_uint32 baud_rate;
00412                 cyg_uint8  tmp;
00413                 va_list    ap;
00414                 //
00415                 // get baud rate from variable argument list
00416                 //
00417                 va_start(ap, __func);
00418                 baud_rate = va_arg(ap, cyg_uint32);
00419                 va_end(ap);
00420                 //
00421                 // disable sci interrupts while changing the hardware
00422                 //
00423                 HAL_READ_UINT8(chan->base + _REG_SCSCR, scr);
00424                 tmp = scr;
00425                 tmp = scr & ~(CYGARC_REG_SCSCR_TIE 
00426                             | CYGARC_REG_SCSCR_RIE
00427                             | CYGARC_REG_SCSCR_MPIE
00428                             | CYGARC_REG_SCSCR_TEIE);
00429                 HAL_WRITE_UINT8(chan->base + _REG_SCSCR, tmp);
00430                 //
00431                 // Now set new baud rate - we have to set BRR and CKS in SCSMR
00432                 //
00433                 HAL_READ_UINT8(chan->base + _REG_SCSMR, tmp);                          
00434                 tmp &= ~CYGARC_REG_SCSMR_CKSx_MASK;
00435                 tmp |= CYGARC_SCBRR_CKSx(baud_rate);
00436                 HAL_WRITE_UINT8(chan->base + _REG_SCSMR, tmp);
00437                 HAL_WRITE_UINT8(chan->base + _REG_SCBRR, CYGARC_SCBRR_N(baud_rate));
00438                 //
00439                 // now restore old scr register settings before disabling interrupts
00440                 //
00441                 HAL_WRITE_UINT8(chan->base + _REG_SCSCR, scr);
00442              } 
00443              break; // End of case __COMMCTL_SETBAUD: 
00444         //
00445         // Query baud rate
00446         //
00447         case __COMMCTL_GETBAUD:
00448              break; 
00449         //
00450         //
00451         //  
00452         default:
00453              ; // do nothing
00454     } // End of switch (__func) 
00455 
00456     CYGARC_HAL_RESTORE_GP();
00457     return ret;
00458 }
00459 
00460 
00461 //=============================================================================
00462 //                          INTERRUPT HANDLER
00480 //=============================================================================
00481 int hal_sci_isr(void         *__ch_data, 
00482                 int          *__ctrlc, 
00483                 CYG_ADDRWORD  __vector, 
00484                 CYG_ADDRWORD  __data)
00485 {
00486     cyg_uint8  c; 
00487     cyg_uint8  sr;
00488     cyg_uint8 *base = ((channel_data_t*)__ch_data)->base;
00489     int        res  = 0;
00490 
00491 
00492     CYGARC_HAL_SAVE_GP();
00493 
00494     *__ctrlc = 0;
00495     HAL_READ_UINT8(base + _REG_SCSSR, sr);
00496     if (sr & CYGARC_REG_SCSSR_ORER) 
00497     {
00498         //
00499         // Serial RX overrun. Clear error and hope protocol recovers.
00500         //
00501         HAL_WRITE_UINT8(base+_REG_SCSSR, 
00502                         CYGARC_REG_SCSSR_CLEARMASK & ~CYGARC_REG_SCSSR_ORER);
00503         res = CYG_ISR_HANDLED;
00504     } 
00505     else if (sr & CYGARC_REG_SCSSR_RDRF) 
00506     {
00507         
00508         HAL_READ_UINT8(base+_REG_SCRDR, c);     // Received character
00509         HAL_WRITE_UINT8(base+_REG_SCSSR,        // Clear buffer full flag.
00510                         CYGARC_REG_SCSSR_CLEARMASK & ~CYGARC_REG_SCSSR_RDRF);
00511 
00512         if(cyg_hal_is_break(&c, 1 ))
00513         {
00514             *__ctrlc = 1;
00515         }
00516 
00517         res = CYG_ISR_HANDLED;
00518     }
00519 
00520     CYGARC_HAL_RESTORE_GP();
00521     return res;
00522 }
00523 #endif // End of #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
00524 
00525 //-----------------------------------------------------------------------------
00526 // end of sci.c

Generated on Tue Feb 17 09:06:12 2004 for eCos EDOSK-2674 HAL by doxygen 1.3.5