gonzui


Format: Advanced Search

mtkernel_3/device/ser/sysdepend/rx231/ser_rx231.cbare sourcepermlink (0.02 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    Device Driver for micro T-Kernel for μT-Kernel 3.0
    4:  *
    5:  *    Copyright (C) 2020-2021 by Ken Sakamura.
    6:  *    This software is distributed under the T-License 2.2.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by TRON Forum(http://www.tron.org) at 2021/08.
   10:  *
   11:  *----------------------------------------------------------------------
   12:  */
   13: 
   14: #include <sys/machine.h>
   15: #ifdef CPU_RX231
   16: 
   17: #include <tk/tkernel.h>
   18: #include <tm/tmonitor.h>
   19: #include "../../ser.h"
   20: #include "../../../include/dev_def.h"
   21: #if DEV_SER_ENABLE
   22: /*
   23:  *      ser_rx231.c
   24:  *      Serial communication device driver
   25:  *      System dependent processing for RX231
   26:  */
   27: 
   28: /*----------------------------------------------------------------------
   29:  * Device register base address
   30:  */
   31: const LOCAL UW ba[DEV_SER_UNITNM] = {
   32:         SCI0_BASE, SCI1_BASE, SCI5_BASE, SCI6_BASE, 
   33:         SCI8_BASE, SCI9_BASE, SCI12_BASE
   34: };
   35: 
   36: /*----------------------------------------------------------------------
   37:  * Interrupt number Table
   38:  */
   39: const LOCAL UINT inotbl[DEV_SER_UNITNM] = {
   40:         INTNO_SCI0_ERI, INTNO_SCI1_ERI, INTNO_SCI5_ERI, INTNO_SCI6_ERI,
   41:         INTNO_SCI8_ERI,INTNO_SCI9_ERI, INTNO_SCI12_ERI
   42: };
   43: #define INTNO_ERI(n)    (inotbl[n])
   44: #define INTNO_RXI(n)    (inotbl[n]+1)
   45: #define INTNO_TXI(n)    (inotbl[n]+2)
   46: #define INTNO_TXE(n)    (inotbl[n]+3)
   47: 
   48: /*----------------------------------------------------------------------
   49:  * Device control data
   50: */
   51: typedef struct {
   52:         UW     mode;               // Serial mode
   53:         UW     speed;              // Spped (bit rate)
   54: } T_DEV_SER_LLDEVCB;
   55: 
   56: LOCAL T_DEV_SER_LLDEVCB         ll_devcb[DEV_SER_UNITNM];
   57: 
   58: /*----------------------------------------------------------------------
   59:  * Interrupt handler
   60:  */
   61: 
   62: /*
   63:  * TXI: Transmit data empty interrupt
   64:  */
   65: void sci_txi_inthdr( UINT intno)
   66: {
   67:         UW     unit, data;
   68: 
   69:         unit = (intno - INTNO_SCI0_TXI) >>2 ;
   70:         if(unit >= DEV_SER_UNITNM ) return;
   71: 
   72:         if( dev_ser_get_snddat(unit, &data)) {
   73:                 out_b(ba[unit] + SCI_TDR, (UB)data);
   74:         }
   75: }
   76: 
   77: /*
   78:  * RXI: Receive data full interrupt
   79:  */
   80: void sci_rxi_inthdr( UINT intno)
   81: {
   82:         UW     unit, data;
   83: 
   84:         unit = (intno - INTNO_SCI0_RXI) >>2 ;
   85:         if(unit >= DEV_SER_UNITNM ) return;
   86: 
   87:         data = in_b(ba[unit] + SCI_RDR);
   88:         dev_ser_notify_rcv(unit, data);        /* Notify the main process of data reception. */
   89: 
   90: }
   91: 
   92: /*
   93:  * ERI: Receive error interrupt
   94:  */
   95: void sci_eri_inthdr( UINT intno)
   96: {
   97:         UW     unit, ssr;
   98: 
   99:         unit = (intno - INTNO_SCI0_ERI) >>2 ;
  100:         if(unit >= DEV_SER_UNITNM ) return;
  101: 
  102:         ssr = in_b(ba[unit] + SCI_SSR);
  103:         out_b(ba[unit] + SCI_SSR, 0);          /* Clear error */
  104: 
  105:         ssr &= (SCI_SSR_ORER | SCI_SSR_PER | SCI_SSR_FER);
  106:         dev_ser_notify_err(unit, ssr); /* Notify error to main process */
  107: }
  108: 
  109: 
  110: /*----------------------------------------------------------------------
  111:  * Set mode & Start communication
  112:  */
  113: LOCAL void start_com(UW unit, UW mode, UW speed)
  114: {
  115:         UB     data;
  116: 
  117:         /* Set communication mode & Speed */
  118:         out_b( ba[unit] + SCI_SMR, (UB)((mode & 0x00000078)|(speed>>8 & 0x00000003)));
  119:         out_b( ba[unit] + SCI_SCMR, 0xF2);
  120:         data = in_b( ba[unit] + SCI_SEMR);
  121:         out_b( ba[unit] + SCI_SEMR, (data & ~SCI_SEMR_ABCS) | (speed & SCI_SEMR_ABCS));
  122:         out_b( ba[unit] + SCI_BRR, speed >>16);
  123: 
  124:         /* SCR.TE,RE,TIE,RIE <- 1 */
  125:         out_b( ba[unit] + SCI_SCR, 
  126:                 (SCI_SCR_RE | SCI_SCR_TE | SCI_SCR_RIE | SCI_SCR_TIE | SCI_SCR_INI));
  127: }
  128: 
  129: /*----------------------------------------------------------------------
  130:  * Stop communication
  131:  */
  132: LOCAL void stop_com(UW unit)
  133: {
  134:         if(unit != DEVCNF_SER_DBGUN) {
  135:                 out_b(ba[unit] + SCI_SCR, SCI_SCR_INI);               /* SCR.TIE,RIE,TE,RE,TEIE <- 0 & Set SCR.CKE */
  136:         } else {       /* Used by T-Monitor */
  137:                 out_b(ba[unit] + SCI_SCR, SCI_SCR_DEBUG);
  138:         }
  139: }
  140: 
  141: /*----------------------------------------------------------------------
  142:  * Calculate baud rate
  143:  */
  144: LOCAL UW calc_brr(UW baud)
  145: {
  146:         UW     abcs, brr, cks;
  147:         W      work;
  148: 
  149:         work = SYSCLK_PCLKB / (baud * 256);
  150:         if(work < 16) {
  151:                 abcs  = SCI_SEMR_ABCS;
  152:                 cks   = 0;
  153:                 brr = SYSCLK_PCLKB / (baud * 16) - 1;
  154:         } else if(work < 32) {
  155:                 abcs  = 0;
  156:                 cks   = 0;
  157:                 brr = SYSCLK_PCLKB / (baud * 32) - 1;
  158:         } else if(work < 64) {
  159:                 abcs  = SCI_SEMR_ABCS;
  160:                 cks   = 1;
  161:                 brr = SYSCLK_PCLKB / (baud * 64) - 1;
  162:         } else if(work < 128) {
  163:                 abcs  = 0;
  164:                 cks   = 1;
  165:                 brr = SYSCLK_PCLKB / (baud * 128) - 1;
  166:         } else if(work < 256) {
  167:                 abcs  = SCI_SEMR_ABCS;
  168:                 cks   = 2;
  169:                 brr = SYSCLK_PCLKB / (baud * 256) - 1;
  170:         } else if(work < 512) {
  171:                 abcs  = 0;
  172:                 cks   = 2;
  173:                 brr = SYSCLK_PCLKB / (baud * 512) - 1;
  174:         } else if(work < 1024) {
  175:                 abcs  = SCI_SEMR_ABCS;
  176:                 cks   = 3;
  177:                 brr = SYSCLK_PCLKB / (baud * 1024) - 1;
  178:         } else if(work < 2048) {
  179:                 abcs  = 0;
  180:                 cks   = 3;
  181:                 brr = SYSCLK_PCLKB / (baud * 2048) - 1;
  182:         } else {
  183:                 return 0;
  184:         }
  185: 
  186:         return (brr<<16 | cks << 8 | abcs);
  187: }
  188: 
  189: /*----------------------------------------------------------------------
  190:  * Low level device control
  191:  */
  192: EXPORT ER dev_ser_llctl( UW unit, INT cmd, UW parm)
  193: {
  194:         UW     data;
  195:         ER     err = E_OK;
  196: 
  197:         switch(cmd) {
  198:         case LLD_SER_MODE:     /* Set Communication mode */
  199:                 ll_devcb[unit].mode = parm;
  200:                 break;
  201:         
  202:         case LLD_SER_SPEED:    /* Set Communication Speed */
  203:                 data = calc_brr(parm);
  204:                 if(data != 0) {
  205:                         ll_devcb[unit].speed = data;
  206:                 } else {
  207:                         err = E_PAR;
  208:                 }
  209:                 break;
  210:         
  211:         case LLD_SER_START:    /* Start communication */
  212:                 /* Clear Interrupt */
  213:                 in_b(ba[unit] + SCI_SSR);
  214:                 out_b(ba[unit] + SCI_SSR, 0xC0);
  215:                 /* Enable Interrupt */
  216:                 EnableInt( INTNO_ERI(unit), DEVCNF_SER_INTPRI);
  217:                 EnableInt( INTNO_RXI(unit), DEVCNF_SER_INTPRI);
  218:                 EnableInt( INTNO_TXI(unit), DEVCNF_SER_INTPRI);
  219:                 /* Set mode & Start communication */
  220:                 start_com( unit, ll_devcb[unit].mode, ll_devcb[unit].speed);
  221:                 break;
  222:         
  223:         case LLD_SER_STOP:
  224:                 /* Disable Interrupt */
  225:                 DisableInt( INTNO_ERI(unit));
  226:                 DisableInt( INTNO_RXI(unit));
  227:                 DisableInt( INTNO_TXI(unit));
  228:                 stop_com(unit);                       // Stop communication
  229:                 break;
  230: 
  231:         case LLD_SER_SEND:
  232:                 if((in_b( ba[unit] + SCI_SSR) & SCI_SSR_TDRF) != 0) {
  233:                         out_b(ba[unit] + SCI_TDR, (UB)parm);
  234:                         err = E_OK;
  235:                 } else {
  236:                         err = E_BUSY;
  237:                 }
  238:                 break;
  239: 
  240:         case LLD_SER_BREAK:    /* Send Break */
  241:                 err = E_NOSPT;
  242:                 break;
  243:         }
  244: 
  245:         return err;
  246: }
  247: 
  248: /*----------------------------------------------------------------------
  249:  * Device initialization
  250:  */
  251: EXPORT ER dev_ser_llinit( T_SER_DCB *p_dcb)
  252: {
  253:         T_DINT         dint;
  254:         UW             unit;
  255:         ER             err;
  256: 
  257:         unit = p_dcb->unit;
  258: 
  259: #if DEVCONF_SER_INIT_MSTP               // Initialize module stop
  260:         const UINT     mstp_bit[] = { 31, 30, 26, 25, 27, 26, 4};
  261:         UINT           sts;
  262:         UW             *mstp;
  263: 
  264:         if(unit == 4 || unit == 5) {
  265:                 mstp = (UB*)MSTPCRC;
  266:         } else {
  267:                 mstp = (UB*)MSTPCRB;
  268:         }
  269: 
  270:         if(in_w(mstp) & (1<<mstp_bit[unit])) {
  271:                 DI(sts);
  272:                 out_h(SYSTEM_PRCR, 0xA502);   /* Disable Register Protect */
  273:                 *mstp &= ~(1<<mstp_bit[unit]);        /* Release module stop */
  274:                 out_h(SYSTEM_PRCR, 0xA500);   /* Enable Register protect */
  275:                 EI(sts);
  276:         }
  277: #endif          /* DEVCONF_SER_INIT_MSTP */
  278: 
  279:         stop_com(unit);                                        /* Stop communication */
  280:         out_b(ba[unit] + SCI_SPMR, SCI_SPMR_INI);      /* Set Hard flow control */
  281: 
  282:         /* Device Control block Initizlize */
  283:         p_dcb->intno_rcv = INTNO_SCI0_RXI + (unit<<2);
  284:         p_dcb->intno_snd = INTNO_SCI0_TXI + (unit<<2);
  285: 
  286:         /* Interrupt handler definition */
  287:         dint.intatr    = TA_HLNG;
  288:         dint.inthdr    = sci_eri_inthdr;
  289:         err = tk_def_int(INTNO_ERI(unit), &dint);
  290:         dint.inthdr    = sci_rxi_inthdr;
  291:         err = tk_def_int(INTNO_RXI(unit), &dint);      
  292:         dint.inthdr    = sci_txi_inthdr;
  293:         err = tk_def_int(INTNO_TXI(unit), &dint);
  294: 
  295:         return err;
  296: }
  297: 
  298: #endif          /* DEV_SER_ENABLE */
  299: #endif          /* CPU_RX231 */