gonzui


Format: Advanced Search

mtkernel_3/device/i2c/sysdepend/stm32l4/i2c_stm32l4.cbare sourcepermlink (0.03 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_STM32L4
   16: 
   17: #include <tk/tkernel.h>
   18: #include "../../i2c.h"
   19: #include "../../../include/dev_def.h"
   20: #if DEV_IIC_ENABLE
   21: /*
   22:  *      i2c_stm32l4.c
   23:   *     I2C device driver
   24:  *      System-dependent definition for STM32L4
   25:  */
   26: 
   27: /*----------------------------------------------------------------------
   28:  * Device register base address
   29: */
   30: const LOCAL UW ba[DEV_I2C_UNITNM] = { I2C1_BASE, I2C2_BASE, I2C3_BASE };
   31: 
   32: #define I2C_CR1(u)      (ba[u] + I2Cx_CR1)
   33: #define I2C_CR2(u)      (ba[u] + I2Cx_CR2)
   34: #define I2C_TIMINGR(u)  (ba[u] + I2Cx_TIMINGR)
   35: #define I2C_ISR(u)      (ba[u] + I2Cx_ISR)
   36: #define I2C_ICR(u)      (ba[u] + I2Cx_ICR)
   37: #define I2C_ICR(u)      (ba[u] + I2Cx_ICR)
   38: #define I2C_RXDR(u)     (ba[u] + I2Cx_RXDR)
   39: #define I2C_TXDR(u)     (ba[u] + I2Cx_TXDR)
   40: 
   41: /*----------------------------------------------------------------------
   42:  * Device data
   43: */
   44: const LOCAL struct {
   45:         UINT   intno;            // Interrupt number
   46:         PRI    intpri;            // Interrupt priority
   47:         TMO    timout;            // I2C timeout time
   48: } ll_devdat[DEV_I2C_UNITNM] = {
   49:         {      /* I2C1 */
   50:                 .intno                = INTNO_I2C1_EV,
   51:                 .intpri               = DEVCNF_I2C1_INTPRI,
   52:                 .timout               = DEVCNF_I2C1_TMO,
   53:         },
   54:         {      /* I2C2 */
   55:                 .intno                = INTNO_I2C2_EV,
   56:                 .intpri               = DEVCNF_I2C2_INTPRI,
   57:                 .timout               = DEVCNF_I2C2_TMO,
   58:         },
   59:         {      /* I2C3 */
   60:                 .intno                = INTNO_I2C3_EV,
   61:                 .intpri               = DEVCNF_I2C3_INTPRI,
   62:                 .timout               = DEVCNF_I2C3_TMO,
   63:         },
   64: };
   65: 
   66: /*----------------------------------------------------------------------
   67:  * Device control data
   68: */
   69: typedef struct {
   70:         ID     wait_tskid; /* Wait Task ID */
   71:         UW     state;              /* Operating state */
   72:         UW     sadr;               /* Slave address */
   73:         ER     ioerr;              /* Communication error */
   74:         UW     sdat_num;   /* Number of send data */
   75:         UW     rdat_num;   /* Number of receive data */
   76:         UB     *sbuf;              /* Send buffer */
   77:         UB     *rbuf;              /* Receive buffer */
   78: } T_I2C_LLDCB;
   79: LOCAL T_I2C_LLDCB       ll_devcb[DEV_I2C_UNITNM];
   80: 
   81: 
   82: /*-------------------------------------------------------
   83:  * Interrupt handler
   84:  */
   85: /*-------------------------------------------------------
   86:  * Event interrupt handler
   87:  */
   88: LOCAL void i2c_evhdr( UINT intno )
   89: {
   90:         T_I2C_LLDCB    *p_cb;
   91:         UW             i2c_st;
   92:         INT            unit;
   93:         BOOL           wup      = FALSE;
   94: 
   95:         for ( unit = 0; unit < DEV_I2C_UNITNM; unit++ ) {
   96:                 if ( ll_devdat[unit].intno == intno ) {
   97:                         p_cb = &ll_devcb[unit];
   98:                         break;
   99:                 }
  100:         }
  101:         if(unit >= DEV_I2C_UNITNM) return;
  102: 
  103:         i2c_st = in_w(I2C_ISR(unit));
  104:         if( i2c_st & I2C_ISR_NACKF) {
  105:                 p_cb->ioerr = E_IO;
  106:                 wup = TRUE;
  107: 
  108:         } else if( i2c_st & I2C_ISR_TXIS) {            /* TX interrupt */
  109:                 out_w(I2C_TXDR(unit),*p_cb->sbuf++);
  110:                 if(--(p_cb->sdat_num) <= 0) {                 /* final data ? */
  111:                         if(p_cb->rdat_num == 0) {
  112:                                 out_w(I2C_CR1(unit), I2C_CR1_PE);
  113:                                 p_cb->state = I2C_STS_STOP;
  114:                                 wup = TRUE;
  115:                         } else {
  116:                                 out_w(I2C_CR1(unit), I2C_CR1_PE | I2C_CR1_TCIE | I2C_CR1_RXIE | I2C_CR1_NACKIE | I2C_CR1_ERRIE );
  117:                         }
  118:                 }
  119: 
  120:         } else if( i2c_st & I2C_ISR_TC) {              /* Transfer complete */
  121:                 out_w(I2C_CR1(unit), I2C_CR1_PE | I2C_CR1_RXIE | I2C_CR1_NACKIE | I2C_CR1_ERRIE );
  122:                 p_cb->state = I2C_STS_START;
  123:                 wup = TRUE;
  124: 
  125:         } else if( i2c_st & I2C_ISR_RXNE) {    /* RX interrupt */
  126:                 *(p_cb->rbuf++) = (UB)in_w(I2C_RXDR(unit));
  127:                 if(--(p_cb->rdat_num) <= 0) {                 /* final data ? */
  128:                         out_w(I2C_CR1(unit), I2C_CR1_PE);
  129:                         p_cb->state = I2C_STS_STOP;
  130:                         wup = TRUE;
  131:                 }
  132:         } else {       /* Error */
  133:                 out_w(I2C_CR1(unit), I2C_CR1_PE);
  134:                 p_cb->ioerr = E_IO;
  135:         }
  136: 
  137:         out_w(I2C_ICR(unit), I2C_ICR_ALL);     // Clear all Interrupt flag
  138:         ClearInt(intno);                       // Clear interrupt
  139: 
  140:         if(wup) {
  141:                 if(p_cb->wait_tskid) {
  142:                         tk_wup_tsk(p_cb->wait_tskid);
  143:                         p_cb->wait_tskid = 0;
  144:                 }
  145:         }
  146: }
  147: 
  148: /*-------------------------------------------------------
  149:  * Error interrupt handler
  150:  */
  151: LOCAL void i2c_erhdr( UINT intno )
  152: {
  153:         T_I2C_LLDCB    *p_cb;
  154:         INT            unit;
  155: 
  156:         intno--;
  157:         for ( unit = 0; unit < DEV_I2C_UNITNM; unit++ ) {
  158:                 if ( ll_devdat[unit].intno == intno ) {
  159:                         p_cb = &ll_devcb[unit];
  160:                         break;
  161:                 }
  162:         }
  163:         if(unit >= DEV_I2C_UNITNM) return;
  164: 
  165:         out_w(I2C_ICR(unit), I2C_ICR_ALL);     // Clear all Interrupt flag
  166:         ClearInt(intno);                       // Clear interrupt
  167:         
  168:         out_w(I2C_CR1(unit), I2C_CR1_PE);
  169: 
  170:         p_cb->ioerr = E_IO;
  171:         if(p_cb->wait_tskid) {
  172:                 tk_wup_tsk(p_cb->wait_tskid);
  173:                 p_cb->wait_tskid = 0;
  174:         }
  175: }
  176: 
  177: /*----------------------------------------------------------------------
  178:  * Execution of communication
  179:  */
  180: LOCAL ER i2c_trans(INT unit, T_I2C_LLDCB *p_cb)
  181: {
  182:         UW             i2c_ctl;
  183:         UINT           imask;
  184:         ER             err;
  185: 
  186:         p_cb->ioerr            = E_OK;
  187:         p_cb->wait_tskid       = 0;
  188: 
  189:         /* I2C Device enable */
  190:         out_w(I2C_CR1(unit), I2C_CR1_PE | I2C_CR1_TXIE | I2C_CR1_RXIE | I2C_CR1_NACKIE | I2C_CR1_ERRIE );
  191: 
  192:         while ((err = p_cb->ioerr) == E_OK ) {
  193: 
  194:                 switch ( p_cb->state ) {
  195:                 case I2C_STS_START:
  196:                         DI(imask);
  197:                         i2c_ctl = p_cb->sadr <<1;
  198:                         if(p_cb->sdat_num > 0 ) {    /* Send */
  199:                                 i2c_ctl |= p_cb->sdat_num <<16 ;
  200:                                 if( p_cb->rdat_num == 0) {
  201:                                         i2c_ctl |= I2C_CR2_AUTOEND;
  202:                                 }
  203:                                 out_w(I2C_CR2(unit), i2c_ctl);
  204:                                 p_cb->state = I2C_STS_SEND;
  205:                         } else {                     /* Receive */
  206:                                 i2c_ctl |= p_cb->rdat_num <<16 | I2C_CR2_RD_WRN | I2C_CR2_AUTOEND;
  207:                                 p_cb->state = I2C_STS_RECV;
  208:                                 out_w(I2C_CR2(unit), i2c_ctl);
  209:                         }
  210: 
  211:                         out_w(I2C_CR2(unit), i2c_ctl | I2C_CR2_START);
  212:                         EI(imask);
  213:                         break;
  214: 
  215:                 case I2C_STS_STOP:
  216:                         while(in_w(I2C_ISR(unit)) & I2C_ISR_BUSY) {
  217:                                 tk_dly_tsk(1);
  218:                         }
  219:                         break;
  220:                 }
  221:                 if ( p_cb->state == I2C_STS_STOP ) break;
  222: 
  223:                 p_cb->wait_tskid = tk_get_tid();
  224:                 err = tk_slp_tsk(ll_devdat[unit].timout);
  225:                 if ( err < E_OK ) break;
  226:         }
  227: 
  228:         out_w(I2C_CR1(unit), 0);       /* I2C Device disable */
  229: 
  230:         return err;
  231: }
  232: 
  233: /*----------------------------------------------------------------------
  234:  * Set communication parameters
  235:  */
  236: Inline void set_com_start(UW unit, UW sadr, UW sdat_num, UW rdat_num, UB *sbuf, UB *rbuf)
  237: {
  238:         ll_devcb[unit].state   = I2C_STS_START;
  239:         ll_devcb[unit].sadr    = sadr;            /* Slave address */
  240:         ll_devcb[unit].sdat_num        = sdat_num;    /* Number of send data */
  241:         ll_devcb[unit].rdat_num        = rdat_num;    /* Number of receive data */
  242:         ll_devcb[unit].sbuf    = sbuf;            /* Send buffer */
  243:         ll_devcb[unit].rbuf    = rbuf;            /* Receive buffer */
  244: }
  245: 
  246: 
  247: /*----------------------------------------------------------------------
  248:  * Low level device control
  249:  */
  250: EXPORT W dev_i2c_llctl( UW unit, INT cmd, UW p1, UW p2, UW *pp)
  251: {
  252:         T_I2C_EXEC     *p_ex;
  253:         ER             err        = E_OK;
  254: 
  255:         switch(cmd) {
  256:         case LLD_I2C_OPEN:
  257:                 /* I2C Initial setting */
  258:                 out_w(I2C_TIMINGR(unit), I2C_TIMINGR_INIT);
  259: 
  260:                 /* I2C interrupt enable */
  261:                 EnableInt(ll_devdat[unit].intno, ll_devdat[unit].intpri);
  262:                 EnableInt(ll_devdat[unit].intno + 1, ll_devdat[unit].intpri);
  263:                 break;
  264: 
  265:         case LLD_I2C_CLOSE:
  266:                 /* I2C interrupt disable */
  267:                 DisableInt(ll_devdat[unit].intno);
  268:                 DisableInt(ll_devdat[unit].intno + 1);
  269:                 break;
  270: 
  271:         case LLD_I2C_READ:
  272:                 set_com_start( unit, p1, 0, p2, NULL, (UB*)pp);
  273:                 err = i2c_trans(unit, &ll_devcb[unit]);
  274:                 if(err >= E_OK) err = p1 - ll_devcb[unit].sdat_num;
  275:                 break;
  276: 
  277:         case LLD_I2C_WRITE:
  278:                 set_com_start( unit, p1, p2, 0, (UB*)pp, NULL);
  279:                 err = i2c_trans(unit, &ll_devcb[unit]);
  280:                 if(err >= E_OK) err = p1 - ll_devcb[unit].sdat_num;
  281:                 break;
  282: 
  283:         case LLD_I2C_EXEC:
  284:                 p_ex = (T_I2C_EXEC*)pp;
  285:                 set_com_start( unit, p_ex->sadr, p_ex->snd_size, p_ex->rcv_size, p_ex->snd_data, p_ex->rcv_data);
  286:                 err = i2c_trans(unit, &ll_devcb[unit]);
  287:                 if(err >= E_OK) err = p_ex->snd_size + p_ex->rcv_size;
  288:                 break;
  289:         }
  290:         
  291:         return (W)err;
  292: }
  293: 
  294: /*----------------------------------------------------------------------
  295:  * Device initialization
  296:  */
  297: EXPORT ER dev_i2c_llinit( T_I2C_DCB *p_dcb)
  298: {
  299:         T_DINT dint;
  300: 
  301:         UW     unit;
  302:         UW     intno;
  303:         ER     err;
  304: 
  305:         unit = p_dcb->unit;
  306: 
  307: #if DEVCONF_I2C_INIT_MCLK
  308:         UW     ccipr;
  309:         ccipr = in_w(RCC_CCIPR) & ~(RCC_CCIPR_I2CSEL << (unit<<1));
  310:         out_w(RCC_CCIPR, ccipr |(DEVCNF_I2CSEL << (12 + (unit<<1))));
  311: 
  312:         *(_UW*)RCC_APB1ENR1 |= (RCC_APB1ENR1_I2C1EN << unit);
  313: #endif
  314: 
  315:         /* Interrupt handler definition */
  316:         intno          = ll_devdat[unit].intno;
  317:         dint.intatr    = TA_HLNG;
  318:         dint.inthdr    = i2c_evhdr;
  319:         
  320:         err = tk_def_int(intno, &dint);                // I2C event interrupt
  321:         if(err < E_OK) return err;
  322: 
  323:         dint.inthdr    = i2c_erhdr;
  324:         err = tk_def_int(intno + 1, &dint);    // I2C error interrupt
  325: 
  326:         return err;
  327: }
  328: 
  329: #endif          /* DEV_IIC_ENABLE */
  330: #endif          /* CPU_TMPM367FDFG */