gonzui


Format: Advanced Search

mtkernel_3/device/i2c/sysdepend/rx231/i2c_rx231.cbare sourcepermlink (0.04 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 "../../i2c.h"
   19: #include "../../../include/dev_def.h"
   20: #if DEV_IIC_ENABLE
   21: /*
   22:  *      i2c_rx231.c
   23:   *     I2C device driver
   24:  *      System-dependent definition for RX231
   25:  */
   26: 
   27: /*----------------------------------------------------------------------
   28:  * Device control data
   29: */
   30: typedef struct {
   31:         ID     wait_tskid; /* Wait Task ID */
   32:         UW     state;              /* Operating state */
   33:         UW     sadr;               /* Slave address */
   34:         ER     ioerr;              /* Communication error */
   35:         UW     sdat_num;   /* Number of send data */
   36:         UW     rdat_num;   /* Number of receive data */
   37:         UB     *sbuf;              /* Send buffer */
   38:         UB     *rbuf;              /* Receive buffer */
   39: } T_I2C_LLDCB;
   40: 
   41: T_I2C_LLDCB     ll_devcb;
   42: 
   43: /*-------------------------------------------------------
   44:  * Interrupt handler
   45:  *-------------------------------------------------------
   46:  */
   47: /*
   48:  * TXI: Transmit data empty interrupt
   49:  */
   50: LOCAL void i2c_txi_inthdr( UINT intno )
   51: {
   52:         UB     reg;
   53: 
   54:         switch(ll_devcb.state) {
   55:         case I2C_STS_START:
   56:                 if(ll_devcb.sdat_num > 0 ) {  /* Send */
   57:                         out_b(RIIC_ICDRT, ll_devcb.sadr);
   58:                         ll_devcb.state = I2C_STS_SEND;
   59:                 } else {                      /* Receive */
   60:                         out_b(RIIC_ICDRT, (ll_devcb.sadr|1));
   61:                         reg = in_b(RIIC_ICIER);
   62:                         out_b(RIIC_ICIER, (reg | RIIC_ICIER_RIE) & ~RIIC_ICIER_TIE);
   63:                         ll_devcb.state = I2C_STS_RECV | I2C_STS_TOP;
   64:                 }
   65:                 break;
   66: 
   67:         case I2C_STS_SEND:
   68:                 if(--(ll_devcb.sdat_num) <= 0) {
   69:                         if(ll_devcb.rdat_num == 0) {
   70:                                 ll_devcb.state = I2C_STS_STOP;
   71:                         } else {
   72:                                 ll_devcb.state = I2C_STS_RESTART;
   73:                         }
   74:                         reg = in_b(RIIC_ICIER);
   75:                         out_b(RIIC_ICIER, (reg | RIIC_ICIER_TEIE) & ~RIIC_ICIER_TIE);
   76:                 }
   77:                 out_b(RIIC_ICDRT, *(ll_devcb.sbuf)++);
   78:                 break;
   79:         }
   80: }
   81: 
   82: /*
   83:  * TEI: Transmission end interrupt
   84:  */
   85: LOCAL void i2c_tei_inthdr( UINT intno )
   86: {
   87:         UB     reg;
   88: 
   89:         switch(ll_devcb.state) {
   90:         case I2C_STS_STOP:
   91:                 reg = in_b(RIIC_ICIER);
   92:                 out_b(RIIC_ICIER, (reg & ~RIIC_ICIER_TEIE) |RIIC_ICIER_SPIE);
   93:                 *(UB*)RIIC_ICCR2 |= RIIC_IICR2_SP;    // Stop condition
   94:                 break;
   95:         
   96:         case I2C_STS_RESTART:
   97:                 out_b( RIIC_ICIER , RIIC_ICIER_TIE | RIIC_ICIER_NAKIE);       /* Enable TXI & NAKI */
   98:                 *(UB*)RIIC_ICCR2 |= RIIC_IICR2_RS;    // Rester condition
   99:                 ll_devcb.state = I2C_STS_START;
  100:                 break;
  101:         }
  102: }
  103: 
  104: 
  105: LOCAL void i2c_rxi_inthdr( UINT intno )
  106: {
  107:         UB     reg;
  108: 
  109:         switch(ll_devcb.state) {
  110:         case I2C_STS_RECV | I2C_STS_TOP:
  111:                 if(ll_devcb.rdat_num <= 2) {  // Last data -2
  112:                         *(UB*)RIIC_ICMR3 |= RIIC_ICMR3_WAIT;
  113:                 }
  114:                 if(ll_devcb.rdat_num == 1) {  //Next is the final data
  115:                         *(UB*)RIIC_ICMR3 |= RIIC_ICMR3_ACKBT;
  116:                         ll_devcb.state = I2C_STS_RECV | I2C_STS_LAST;
  117:                 } else {
  118:                         ll_devcb.state = I2C_STS_RECV;
  119:                 }
  120:                 in_b(RIIC_ICDRR);     // Dummy read
  121:                 break;
  122: 
  123:         case I2C_STS_RECV:
  124:                 if(ll_devcb.rdat_num == 3) {  // Last data -2
  125:                         *(UB*)RIIC_ICMR3 |= RIIC_ICMR3_WAIT;
  126:                 }
  127:                 if(ll_devcb.rdat_num == 2) {  //Next is the final data
  128:                         *(UB*)RIIC_ICMR3 |= RIIC_ICMR3_ACKBT;
  129:                         ll_devcb.state = I2C_STS_RECV | I2C_STS_LAST;
  130:                 }
  131:                 *ll_devcb.rbuf++ = in_b(RIIC_ICDRR);
  132:                 ll_devcb.rdat_num--;
  133:                 break;
  134: 
  135:         case I2C_STS_RECV | I2C_STS_LAST:
  136:                 *(UB*)RIIC_ICSR2 &= ~RIIC_ICSR2_STOP;
  137:                 reg = in_b(RIIC_ICIER);
  138:                 out_b(RIIC_ICIER, (reg | RIIC_ICIER_SPIE) & ~RIIC_ICIER_RIE);
  139:                 *(UB*)RIIC_ICCR2 |= RIIC_IICR2_SP;
  140:                 *ll_devcb.rbuf++ = in_b(RIIC_ICDRR);
  141:                 *(UB*)RIIC_ICMR3 &= ~RIIC_ICMR3_WAIT;
  142:                 ll_devcb.state = I2C_STS_STOP;
  143:                 break;
  144:         }
  145: }
  146: 
  147: LOCAL void i2c_eei_inthdr( UINT intno )
  148: {
  149:         UB     reg;
  150: 
  151:         reg = in_b(RIIC_ICSR2);
  152: 
  153:         if(reg & RIIC_ICSR2_STOP) {            /* Detects stop condition */
  154:                 if (ll_devcb.state != I2C_STS_STOP) {
  155:                         ll_devcb.ioerr = E_IO;
  156:                 }
  157:                 out_b( RIIC_ICIER, 0);
  158:                 if(ll_devcb.wait_tskid) {
  159:                         tk_wup_tsk(ll_devcb.wait_tskid);
  160:                         ll_devcb.wait_tskid = 0;
  161:                 }
  162:         } else {
  163:                 ll_devcb.ioerr = E_IO;
  164:                 ll_devcb.state = I2C_STS_STOP;
  165:                 *(UB*)RIIC_ICSR2 &= ~RIIC_ICSR2_STOP;
  166:                 out_b( RIIC_ICIER, RIIC_ICIER_SPIE);
  167:                 *(UB*)RIIC_ICCR2 |= RIIC_IICR2_SP;    /* Stop condition */
  168:         }
  169: }
  170: 
  171: 
  172: /*----------------------------------------------------------------------
  173:  * Execution of communication
  174:  */
  175: LOCAL ER i2c_trans( void)
  176: {
  177:         UB             reg;
  178:         ER             err;
  179: 
  180:         if( in_b(RIIC_ICCR2) & RIIC_IICR2_BBSY) {
  181:                 ll_devcb.ioerr = E_BUSY;              /* I2C bus busy */
  182:                 return E_BUSY;
  183:         }
  184: 
  185:         ll_devcb.ioerr         = E_OK;
  186:         ll_devcb.wait_tskid    = tk_get_tid();
  187: 
  188:         out_b( RIIC_ICIER , RIIC_ICIER_TIE | RIIC_ICIER_NAKIE);        /* Enable TXI & NAKI */
  189: //      out_b( RIIC_ICIER , 0xFF);   /* Enable TXI & NAKI */
  190:         *(UB*)RIIC_ICCR2 |= RIIC_IICR2_ST;             /* start condition */
  191: 
  192:         err = tk_slp_tsk(DEVCNF_I2C_TMO);
  193:         if ( ll_devcb.ioerr != E_OK ) {
  194:                 err = ll_devcb.ioerr;
  195:         }
  196: 
  197:         out_b( RIIC_ICIER, 0);
  198:         reg = in_b(RIIC_ICSR2);
  199:         out_b( RIIC_ICSR2, reg & ~RIIC_ICSR2_STOP & ~RIIC_ICSR2_NACKF);
  200: 
  201:         return err;
  202: }
  203: 
  204: /*----------------------------------------------------------------------
  205:  * Set communication start parameters
  206:  */
  207: Inline void set_com_start(UW sadr, UW sdat_num, UW rdat_num, UB *sbuf, UB *rbuf)
  208: {
  209:         ll_devcb.state         = I2C_STS_START;
  210:         ll_devcb.sadr          = sadr<<1;      /* Slave address */
  211:         ll_devcb.sdat_num      = sdat_num;  /* Number of send data */
  212:         ll_devcb.rdat_num      = rdat_num;  /* Number of receive data */
  213:         ll_devcb.sbuf          = sbuf;         /* Send buffer */
  214:         ll_devcb.rbuf          = rbuf;         /* Receive buffer */
  215: }
  216: 
  217: /*----------------------------------------------------------------------
  218:  * Low level device control
  219:  */
  220: EXPORT W dev_i2c_llctl( UW unit, INT cmd, UW p1, UW p2, UW *pp)
  221: {
  222:         T_I2C_EXEC     *p_ex;
  223:         ER             err        = E_OK;
  224: 
  225:         switch(cmd) {
  226:         case LLD_I2C_OPEN:
  227:                 /* I2C Device reset */
  228:                 out_b( RIIC_ICCR1, RIIC_ICCR1_IICRST | RIIC_ICCR1_SOWP);
  229:                 out_b( RIIC_ICCR1, RIIC_ICCR1_IICRST| RIIC_ICCR1_ICE | RIIC_ICCR1_SOWP);
  230: 
  231:                 /* I2C Initial setting */
  232:                 out_b( RIIC_ICSER, 0);
  233:                 out_b( RIIC_ICMR1, DEVCNF_I2C_CKS<<4 );
  234:                 //out_b( RIIC_ICMR3, RIIC_ICMR3_ACKWP);
  235:                 out_b( RIIC_ICBRH, RIIC_ICBRH_INI);
  236:                 out_b( RIIC_ICBRL, RIIC_ICBRL_INI);
  237: 
  238:                 /* Interrupt initialize */
  239:                 out_b( RIIC_ICIER, 0);
  240:                 out_b( RIIC_ICSR2, 0);
  241:                 EnableInt( INTNO_RIIC_EEI, DEVCNF_I2C_INTPRI);
  242:                 EnableInt( INTNO_RIIC_RXI, DEVCNF_I2C_INTPRI);
  243:                 EnableInt( INTNO_RIIC_TXI, DEVCNF_I2C_INTPRI);
  244:                 EnableInt( INTNO_RIIC_TEI, DEVCNF_I2C_INTPRI);
  245: 
  246:                 /* Release reset */
  247:                 out_b( RIIC_ICCR1,  RIIC_ICCR1_ICE | RIIC_ICCR1_SOWP);
  248:                 break;
  249: 
  250:         case LLD_I2C_CLOSE:
  251:                 /* Disable I2C interrupt */
  252:                 DisableInt(INTNO_RIIC_EEI);
  253:                 DisableInt(INTNO_RIIC_RXI);
  254:                 DisableInt(INTNO_RIIC_TXI);
  255:                 DisableInt(INTNO_RIIC_TEI);
  256:                 break;
  257: 
  258:         case LLD_I2C_READ:
  259:                 set_com_start( p1, 0, p2, NULL, (UB*)pp);
  260:                 err = i2c_trans();
  261:                 if(err >= E_OK) err = p1 - ll_devcb.sdat_num;
  262:                 break;
  263: 
  264:         case LLD_I2C_WRITE:
  265:                 set_com_start( p1, p2, 0, (UB*)pp, NULL);
  266:                 err = i2c_trans();
  267:                 if(err >= E_OK) err = p1 - ll_devcb.sdat_num;
  268:                 break;
  269: 
  270:         case LLD_I2C_EXEC:
  271:                 p_ex = (T_I2C_EXEC*)pp;
  272:                 set_com_start( (p_ex->sadr), p_ex->snd_size, p_ex->rcv_size, p_ex->snd_data, p_ex->rcv_data);
  273:                 err = i2c_trans();
  274:                 if(err >= E_OK) err = p_ex->snd_size + p_ex->rcv_size;
  275:                 break;
  276:         }
  277:         
  278:         return (W)err;
  279: }
  280: 
  281: /*----------------------------------------------------------------------
  282:  * Device initialization
  283:  */
  284: EXPORT ER dev_i2c_llinit( T_I2C_DCB *p_dcb)
  285: {
  286:         T_DINT dint;
  287:         ER     err;
  288: 
  289: #if DEVCONF_I2C_INIT_MSTP               // Initialize module stop
  290:         UINT   sts;
  291: 
  292:         if(in_w(MSTPCRB) & (1<<21)) {
  293:                 DI(sts);
  294:                 out_h(SYSTEM_PRCR, 0xA502);           // Disable Register Protect
  295:                 *(UW*)(MSTPCRB) &= ~(1<<21);          // Release module stop
  296:                 out_h(SYSTEM_PRCR, 0xA500);           // Enable Register protect
  297:                 EI(sts);
  298: 
  299:         }
  300: #endif  /* DEVCONF_I2C_INIT_MSTP */
  301: 
  302:         *(UB*)RIIC_ICCR1 &= ~RIIC_ICCR1_ICE;           // Disable RIIC
  303: 
  304: #if DEVCONF_I2C_INIT_PIN                // Initialize I/O pin
  305:         /* Set pin-function   P16 = SCL0, P17 = SDA0 */
  306:         out_b(MPC_PWPR, 0);                            // PWPR.B0WI = 0
  307:         out_b(MPC_PWPR, MPC_PWMR_PFSWE);               // PWPR.PFSWE = 1
  308:         out_b(MPC_P1nPFS(6), 0x0F);                    // P16 = SCL0
  309:         out_b(MPC_P1nPFS(7), 0x0F);                    // P17 = SDA0
  310:         out_b(MPC_PWPR, MPC_PWMR_B0WI);                        // PWPR.PFSWE = 0, PWPR.B0WI = 1
  311: 
  312:         out_b(PORT1_ODR1, 0x50);                       // Set to open drain
  313:         out_b(PORT1_PMR, 0xC0);                                // Set as peripheral function
  314: 
  315: #endif  /* DEVCONF_I2C_INIT_PIN */
  316: 
  317:         /* Interrupt handler definition */
  318:         dint.intatr    = TA_HLNG;
  319:         dint.inthdr    = i2c_eei_inthdr;
  320:         err = tk_def_int(INTNO_RIIC_EEI, &dint);
  321: 
  322:         dint.inthdr    = i2c_rxi_inthdr;
  323:         err = tk_def_int(INTNO_RIIC_RXI, &dint);
  324: 
  325:         dint.inthdr    = i2c_txi_inthdr;
  326:         err = tk_def_int(INTNO_RIIC_TXI, &dint);
  327: 
  328:         dint.inthdr    = i2c_tei_inthdr;
  329:         err = tk_def_int(INTNO_RIIC_TEI, &dint);
  330: 
  331:         return err;
  332: }
  333: 
  334: #endif          /* DEV_IIC_ENABLE */
  335: #endif          /* CPU_RX231 */