gonzui


Format: Advanced Search

mtkernel_3/device/adc/sysdepend/stm32l4/adc_stm32l4.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_STM32L4
   16: 
   17: #include <tk/tkernel.h>
   18: #include "../../adc.h"
   19: #include "../../../include/dev_def.h"
   20: #if DEV_ADC_ENABLE
   21: /*
   22:  *      dev_adc_stm32l4.c
   23:  *      A/D converter device driver
   24:  *      System dependent processing for STM32L4
   25:  */
   26: 
   27: /*----------------------------------------------------------------------
   28:  * Device register base address
   29: */
   30: const LOCAL UW ba[DEV_ADC_UNITNM] = { ADC1_BASE, ADC2_BASE, ADC3_BASE };
   31: 
   32: #define ADC_ISR(x)      (ba[x] + ADCx_ISR)   // Interrupt & status register
   33: #define ADC_IER(x)      (ba[x] + ADCx_IER)   // Interrupt enable register
   34: #define ADC_CR(x)       (ba[x] + ADCx_CR)     // Control register
   35: #define ADC_SMPR1(x)    (ba[x] + ADCx_SMPR1)       // Sampling time register 1
   36: #define ADC_SMPR2(x)    (ba[x] + ADCx_SMPR2)       // Sampling time register 2
   37: #define ADC_SQR1(x)     (ba[x] + ADCx_SQR1) // Regular sequence register
   38: #define ADC_DR(x)       (ba[x] + ADCx_DR)     // Regular data register
   39: 
   40: 
   41: /*----------------------------------------------------------------------
   42:  * Device control data
   43: */
   44: LOCAL struct {
   45:         ID     wait_tskid;
   46:         UW     smpr1, smpr2;
   47: } ll_devcb[DEV_ADC_UNITNM] = {
   48: 
   49:         {0, DEVCONF_ADC1_SMPR1, DEVCONF_ADC1_SMPR2},
   50:         {0, DEVCONF_ADC2_SMPR1, DEVCONF_ADC2_SMPR2},
   51:         {0, DEVCONF_ADC3_SMPR1, DEVCONF_ADC3_SMPR2}    
   52: };
   53: 
   54: 
   55: /*----------------------------------------------------------------------
   56:  * Interrupt handler
   57:  */
   58: void adc_inthdr( UINT intno)
   59: {
   60:         UW     unit;
   61: 
   62:         if(intno == INTNO_INTADC3) {
   63:                 unit = DEV_ADC_3;
   64:         } else if( in_w(ADC_ISR(DEV_ADC_1))) {
   65:                 unit = DEV_ADC_1;
   66:         } else if( in_w(ADC_ISR(DEV_ADC_2))) {
   67:                 unit = DEV_ADC_2;
   68:         } else {
   69:                 return;
   70:         }
   71: 
   72:         if(ll_devcb[unit].wait_tskid) {
   73:                 tk_wup_tsk(ll_devcb[unit].wait_tskid);
   74:         }
   75: 
   76:         out_w(ADC_ISR(unit), 0x000007FF);      // Clear all interrupt flag.
   77:         ClearInt((unit == DEV_ADC_3)?INTNO_INTADC3:INTNO_INTADC1_2);
   78: }
   79: 
   80: /*----------------------------------------------------------------------
   81:  * A/D convert
   82:  */
   83: LOCAL UW adc_convert( UINT unit, INT ch, INT size, UW *buf )
   84: {
   85:         _UW    *sqr;
   86:         UINT   sqsz, sqch, sqpos;
   87:         UW     rtn;
   88:         ER     err;
   89: 
   90:         if((ch >= ADC_CH_NUM) || (size > ADC_MAX_SQ) || ((ch+size) > ADC_CH_NUM)) return (UW)E_PAR;
   91: 
   92:         out_w(ADC_SQR1(unit), size-1);         // Set channel sequence length.
   93:         
   94:         /* Set channel sequence */
   95:         sqr = (UW*)ADC_SQR1(unit);
   96:         sqsz = size; sqch = ch; sqpos = 6;
   97:         while(sqsz--) {
   98:                 *sqr |= (sqch++)<<sqpos;
   99:                 if((sqpos += 6) >= 32) {
  100:                         sqpos = 0;
  101:                         *(++sqr) = 0; 
  102:                 }
  103:         }
  104: 
  105:         ll_devcb[unit].wait_tskid = tk_get_tid();
  106:         tk_can_wup(TSK_SELF);
  107:         out_w(ADC_CR(unit), ADC_CR_ADSTART | ADC_CR_ADVREGEN); // Start Covert
  108:         for( rtn = 0; rtn < size; rtn++) {
  109:                 err = tk_slp_tsk(DEVCNF_ADC_TMOSCAN);
  110:                 if(err < E_OK) {
  111:                         rtn = err;
  112:                         break;
  113:                 }
  114:                 *buf++ = in_w(ADC_DR(unit));                  // Read deta
  115:         }
  116:         ll_devcb[unit].wait_tskid = 0;
  117: 
  118:         return rtn;
  119: }
  120: 
  121: 
  122: /*----------------------------------------------------------------------
  123:  * A/DC open
  124:  */
  125: LOCAL ER adc_open(UW unit)
  126: {
  127:         ER     err = E_OK;
  128: 
  129:         /* Set sampling time */
  130:         out_w(ADC_SMPR1(unit), ll_devcb[unit].smpr1);
  131:         out_w(ADC_SMPR2(unit), ll_devcb[unit].smpr2);
  132: 
  133:         /* Initialize interrupt */
  134:         out_w(ADC_ISR(unit), 0x000007FF);                      // Clear all interrupt flag.
  135:         out_w(ADC_IER(unit), ADC_IER_ADRDYIE | ADC_IER_EOCIE); // Set Interrupt mask.
  136:         if(unit != DEV_ADC_3) {
  137:                 EnableInt(INTNO_INTADC1_2, DEVCNF_ADC12_INTPRI);
  138:         } else {
  139:                 EnableInt(INTNO_INTADC3, DEVCNF_ADC3_INTPRI);
  140:         }
  141: 
  142:         /* Enable ADC */
  143:         ll_devcb[unit].wait_tskid = tk_get_tid();
  144:         out_w(ADC_CR(unit), ADC_CR_ADEN | ADC_CR_ADVREGEN);    // Set ADEN
  145: 
  146:         err = tk_slp_tsk(DEVCNF_ADC_TMOSCAN);
  147:         if(err < E_OK) err = E_TMOUT;
  148:         ll_devcb[unit].wait_tskid = 0;
  149: 
  150:         return err;
  151: }
  152: 
  153: /*----------------------------------------------------------------------
  154:  * A/DC close
  155:  */
  156: LOCAL void adc_close(UW unit)
  157: {
  158:         DisableInt((unit==DEV_ADC_3)?INTNO_INTADC3:INTNO_INTADC1_2);
  159: 
  160:         /* Disable ADC */
  161:         out_w(ADC_CR(unit), ADC_CR_ADDIS);             // Set ADDIS
  162:         while(in_w(ADC_ISR(unit)) & ADC_ISR_ADRDY);    // Wait until ADEN is clear
  163: }
  164: 
  165: /*----------------------------------------------------------------------
  166:  * Low level device control
  167:  */
  168: EXPORT W dev_adc_llctl( UW unit, INT cmd, UW p1, UW p2, UW *pp)
  169: {
  170:         W      rtn  = (W)E_OK;
  171: 
  172:         switch(cmd) {
  173:         case LLD_ADC_OPEN:     /* Open A/DC */
  174:                 rtn = (W)adc_open(unit);
  175:                 break;
  176: 
  177:         case LLD_ADC_CLOSE:    /* Close A/DC */
  178:                 adc_close(unit);
  179:                 break;
  180:         
  181:         case LLD_ADC_READ:     /* Read A/DC data */
  182:                 rtn = adc_convert(unit, p1, p2, pp);
  183:                 break;
  184:         
  185:         case LLD_ADC_RSIZE:    /* Get read data size */
  186:                 rtn = ADC_CH_NUM - p1;
  187:                 if(rtn < 0 ) rtn = 0;
  188:                 break;
  189:         }
  190:         
  191:         return rtn;
  192: }
  193: 
  194: /*----------------------------------------------------------------------
  195:  * Device initialization
  196:  */
  197: EXPORT ER dev_adc_llinit( T_ADC_DCB *p_dcb)
  198: {
  199:         static BOOL    uninit     = TRUE;     // Uninitialized flag
  200: 
  201:         const T_DINT   dint = {
  202:                 .intatr       = TA_HLNG,
  203:                 .inthdr       = adc_inthdr
  204:         };
  205:         UW     unit;
  206:         ER     err;
  207: 
  208: #if DEVCONF_ADC_INIT_MCLK
  209:         UW     ccipr;
  210: 
  211:         if(uninit) {
  212:                 switch(DEVCNF_ADCSEL) {       // ADC clock source
  213:                 case 1:
  214:                         *(_UW*)RCC_CR |= RCC_CR_PLLSAI1ON;   // PLLSA1 enable
  215:                         *(_UW*)RCC_PLLSAI1CFGR |= 1<<24;     // PLLADC1CLK enable
  216:                         break;
  217:                 case 2:
  218:                         *(_UW*)RCC_CR |= RCC_CR_PLLSAI2ON;   // PLLSA2 enable
  219:                         *(_UW*)RCC_PLLSAI2CFGR |= 1<<24;     // PLLADC2CLK enable
  220:                         break;
  221:                 default:
  222:                         if(DEVCNF_ADCSEL > 3) return E_IO;
  223:                 }
  224:                 ccipr = in_w(RCC_CCIPR) & ~RCC_CCIPR_ADCSEL;
  225:                 out_w(RCC_CCIPR, ccipr | (DEVCNF_ADCSEL << 28));
  226: 
  227:                 *(_UW*)RCC_AHB2ENR |= RCC_AHB2ENR_ADCEN;      // ADC enable
  228:         }
  229: #endif
  230: 
  231:         unit = p_dcb->unit;
  232: 
  233:         /* ADC Power-On */
  234:         out_w(ADC_CR(unit), 0);                                        // DEEPPWD = 0 
  235:         out_w(ADC_CR(unit), ADC_CR_ADVREGEN);                  // ADVREGEN = 1
  236: 
  237:         /* Common ADC settings */
  238:         if(uninit) {
  239:                 out_w(ADC_CCR, 
  240:                         ((DEVCNF_ADC_CKMODE & 0x03)<< 16)    // ADC clock mode
  241:                         |((DEVCNF_ADC_PRESC & 0x0F)<< 18)    // ADC prescaler
  242:                 );
  243:         }
  244: 
  245:         /* ADC calibration */
  246:         out_w(ADC_CR(unit), ADC_CR_ADVREGEN | ADC_CR_ADCAL);   // ADCAL = 1
  247:         while( in_w(ADC_CR(unit)) & ADC_CR_ADCAL);             // Wait until ADCAL is clear
  248: 
  249:         /* Interrupt handler definition */
  250:         err = tk_def_int((unit == DEV_ADC_3)?INTNO_INTADC3:INTNO_INTADC1_2, &dint);
  251: 
  252:         uninit = FALSE;
  253:         return err;
  254: }
  255: 
  256: #endif          /* DEV_ADC_ENABLE */
  257: #endif          /* CPU_STM32L4 */