[Aurix TC275] ADC - 3

사이킷·2025년 1월 18일

AURIX MCU

목록 보기
5/13

ADC Group 초기화 코드

이전 장에서는 ADC 모듈을 초기화하는 코드를 공부해보았다.
이번에는 ADC 모듈의 Group (Arbiter,Converter) 를 초기화하는 코드를 살펴보겠다.

/* create group config */
    IfxVadc_Adc_GroupConfig adcGroupConfig;
    IfxVadc_Adc_initGroupConfig(&adcGroupConfig, &g_VadcAutoScan.vadc);

    /* with group 0 */
    adcGroupConfig.groupId = IfxVadc_GroupId_0;
    adcGroupConfig.master = adcGroupConfig.groupId;

    /* enable scan source */
    adcGroupConfig.arbiter.requestSlotScanEnabled = TRUE;

    /* enable auto scan */
    adcGroupConfig.scanRequest.autoscanEnabled = TRUE;

    /* enable all gates in "always" mode (no edge detection) */
    adcGroupConfig.scanRequest.triggerConfig.gatingMode = IfxVadc_GatingMode_always;

    /* initialize the group */
    IfxVadc_Adc_initGroup(&g_VadcAutoScan.adcGroup, &adcGroupConfig);

시작은 비슷하다. IfxVadc_Adc_GroupConfig adcGroupConfig를 선언하고
IfxVadc_Adc_initGroupConfig() 함수를 통해 초기 설정값을 불러온다.

void IfxVadc_Adc_initGroupConfig(IfxVadc_Adc_GroupConfig *config, IfxVadc_Adc *vadc)
{
   static const IfxVadc_Adc_GroupConfig IfxVadc_Adc_defaultGroupConfig = {
       .arbiter                              = {
           .arbiterRoundLength               = IfxVadc_ArbitrationRounds_4_slots,
           .requestSlotQueueEnabled          = FALSE,
           .requestSlotScanEnabled           = FALSE,
           .requestSlotBackgroundScanEnabled = FALSE,
       },
       .backgroundScanRequest                = {
           .autoBackgroundScanEnabled   = FALSE,
           .triggerConfig.gatingMode    = IfxVadc_GatingMode_disabled,
           .triggerConfig.triggerMode   = IfxVadc_TriggerMode_noExternalTrigger,
           .triggerConfig.gatingSource  = IfxVadc_GatingSource_0,
           .triggerConfig.triggerSource = IfxVadc_TriggerSource_0,
           .requestSlotPrio             = IfxVadc_RequestSlotPriority_low,
           .requestSlotStartMode        = IfxVadc_RequestSlotStartMode_waitForStart,
       },
       .scanRequest                          = {
           .autoscanEnabled             = FALSE,
           .triggerConfig.gatingMode    = IfxVadc_GatingMode_disabled,
           .triggerConfig.gatingSource  = IfxVadc_GatingSource_0,
           .triggerConfig.triggerMode   = IfxVadc_TriggerMode_noExternalTrigger,
           .triggerConfig.triggerSource = IfxVadc_TriggerSource_0,
           .requestSlotPrio             = IfxVadc_RequestSlotPriority_low,
           .requestSlotStartMode        = IfxVadc_RequestSlotStartMode_waitForStart,
       },
       .queueRequest                         = {
           .flushQueueAfterInit         = TRUE,
           .triggerConfig.gatingMode    = IfxVadc_GatingMode_disabled,
           .triggerConfig.gatingSource  = IfxVadc_GatingSource_0,
           .triggerConfig.triggerMode   = IfxVadc_TriggerMode_noExternalTrigger,
           .triggerConfig.triggerSource = IfxVadc_TriggerSource_0,
           .requestSlotPrio             = IfxVadc_RequestSlotPriority_low,
           .requestSlotStartMode        = IfxVadc_RequestSlotStartMode_waitForStart,
       },

       .inputClass[0].resolution = IfxVadc_ChannelResolution_12bit,
       .inputClass[0].sampleTime = 1.0e-6,                           /* Set sample time to 1us */
       .inputClass[1].resolution = IfxVadc_ChannelResolution_12bit,
       .inputClass[1].sampleTime = 1.0e-6,                           /* Set sample time to 1us */
   };

   *config                        = IfxVadc_Adc_defaultGroupConfig;
   config->groupId                = IfxVadc_GroupId_0;
   config->module                 = vadc;
   config->master                 = config->groupId;
   config->disablePostCalibration = FALSE;
}

해당 초기값을 불러오고 다음 부분 부터 설정값을 원하는 것으로 바꿔준다.
autoscan 을 사용할때 예시이다.

/* with group 0 */
    adcGroupConfig.groupId = IfxVadc_GroupId_0;
    adcGroupConfig.master = adcGroupConfig.groupId;

    /* enable scan source */
    adcGroupConfig.arbiter.requestSlotScanEnabled = TRUE;

    /* enable auto scan */
    adcGroupConfig.scanRequest.autoscanEnabled = TRUE;

    /* enable all gates in "always" mode (no edge detection) */
    adcGroupConfig.scanRequest.triggerConfig.gatingMode = IfxVadc_GatingMode_always;

먼저 groupId 설정이다. 0번째 adc group을 설정하는 부분이다.

    adcGroupConfig.groupId = IfxVadc_GroupId_0;
    adcGroupConfig.master = adcGroupConfig.groupId;

다음으로는 Arbiter의 설정을 해주는 코드이다.

/* enable scan source */
    adcGroupConfig.arbiter.requestSlotScanEnabled = TRUE;

arbiter에게 autoscan 소스의 우선순위를 설정하게 해준다.

다음은 auto scan enable해주는 코드부분이다.

adcGroupConfig.scanRequest.autoscanEnabled = TRUE;

다음은 Gating mode 설정이다.

adcGroupConfig.scanRequest.triggerConfig.gatingMode = IfxVadc_GatingMode_always;

GatingMode 의 종류는 다음과 같다.
IfxVadc_GatingMode_disabled : 게이팅 신호를 무시하며, 변환 요청이 실행되지않는다.

IfxVadc_GatingMode_always : 변환 요청이 항상 실행된다.

IfxVadc_GatingMode_gatingHigh : 게이팅 신호가 High일 때만 변환 요청이 실행

IfxVadc_GatingMode_gatingLow : 게이팅 신호가 Low일 때만 변환 요청이 실행

겸사겸사 TriggerMode 도 보겠다.
TriggerMode 설정은 변환 요청을 발생시키는 모드를 말한다.

IfxVadc_TriggerMode_noExternalTrigger : 어떠한 외부 트리거도 두지 않는다.

IfxVadc_TriggerMode_uponFallingEdge : 외부 트리거의 신호가 Falling Edge일 때 변환 요청을 넣는다.

IfxVadc_TriggerMode_uponRisingEdge : 외부 트리거의 신호가 Rising Edge일 때 변환 요청을 넣는다.

IfxVadc_TriggerMode_uponAnyEdge : 외부 트리거의 신호가 Rising이든 Falling 이든 Edge 일 때 변환 요청을 넣는다.

초기화

원하는 설정을 완료하였다면 이제 초기화를 진행한다.

IfxVadc_Adc_initGroup(&g_VadcAutoScan.adcGroup, &adcGroupConfig);
IfxVadc_Status IfxVadc_Adc_initGroup(IfxVadc_Adc_Group *group, const IfxVadc_Adc_GroupConfig *config)
{
.
.
.
    if (config->arbiter.requestSlotScanEnabled == TRUE)
    {
        /* Setup Arbitration priority and turn on enabled slot */
        /* Enable Arbiter slot, set Priority and start mode */
        IfxVadc_setArbiterPriority(vadcG, config->arbiter.requestSlotScanEnabled, config->scanRequest.requestSlotPrio, config->scanRequest.requestSlotStartMode, IfxVadc_RequestSource_scan);
    }
    else
    {
        /* Disable the slot */
        IfxVadc_setArbiterPriority(vadcG, FALSE, IfxVadc_RequestSlotPriority_lowest, IfxVadc_RequestSlotStartMode_waitForStart, IfxVadc_RequestSource_scan);
    }
.
.
.
    /* Setup scan request if enabled */
    if (config->arbiter.requestSlotScanEnabled == TRUE)
    {
        const IfxVadc_Adc_ScanConfig *scanSlot = &config->scanRequest;

        /* configure external Trigger if enabled */
        if (scanSlot->triggerConfig.triggerMode != IfxVadc_TriggerMode_noExternalTrigger)
        {
            /* enable external trigger */
            IfxVadc_enableScanSlotExternalTrigger(vadcG);

            IfxVadc_setScanSlotTriggerConfig(vadcG, scanSlot->triggerConfig.triggerMode, scanSlot->triggerConfig.triggerSource);

            if (scanSlot->triggerConfig.triggerSource == IfxVadc_TriggerSource_15)    /* if last input is used the trigger input selection is extend by Gating inputs */
            {
                IfxVadc_setScanSlotGatingConfig(vadcG, scanSlot->triggerConfig.gatingSource, IfxVadc_GatingMode_always);
            }
            else
            {
                /* do nothing, gating is configured later */
            }
        }
        else
        {
            IfxVadc_disableScanSlotExternalTrigger(vadcG);
        }

        /* configure Gating if enabled */
        if ((scanSlot->triggerConfig.triggerSource != IfxVadc_TriggerSource_15))
        {
            IfxVadc_setScanSlotGatingConfig(vadcG, scanSlot->triggerConfig.gatingSource, scanSlot->triggerConfig.gatingMode);
        }
        else
        {
            /* do nothing, handled by trigger settings */
        }

        IfxVadc_setAutoScan(vadcG, scanSlot->autoscanEnabled ? 1 : 0);
    }
.
.
.

첫번째로 확인할 부분은 IfxVadc_setArbiterPriority() 함수이다.
우리는 arbiter.requestSlotScanEnabled를 True로 설정하였으니 저 함수가 실행된다.

void IfxVadc_setArbiterPriority(Ifx_VADC_G *vadcG, boolean slotEnable, IfxVadc_RequestSlotPriority prio, IfxVadc_RequestSlotStartMode mode, IfxVadc_RequestSource slot)
{
    if (slotEnable != FALSE)
    {
        vadcG->ARBPR.U |= slotEnable << (IFX_VADC_G_ARBPR_ASEN0_OFF + slot); /* enable Slot */
        vadcG->ARBPR.U &= ~(IFX_VADC_G_ARBPR_PRIO0_MSK << (slot * 4u));      /* clear Priority */
        vadcG->ARBPR.U |= (prio << (slot * 4u));                             /* Set Priority */

        if (mode != IfxVadc_RequestSlotStartMode_waitForStart)
        {
            vadcG->ARBPR.U |= 0x1u << (IFX_VADC_G_ARBPR_CSM0_OFF + (slot * 4u)); /* Set cancel inject mode */
        }
        else
        {
            vadcG->ARBPR.U &= ~(0x1u << (IFX_VADC_G_ARBPR_CSM0_OFF + (slot * 4u)));  /* Set Wait for Start mode */
        }
    }
    else
    {
        vadcG->ARBPR.U &= ~(IFX_VADC_G_ARBPR_ASEN0_MSK << (IFX_VADC_G_ARBPR_ASEN0_OFF + slot));  /* disable Slot */
    }
}

언뜻보기에도 VADC 모듈의 ARBPR 레지스터값을 수정하는 것으로 보인다.

Group 0 를 사용하니 레지스터의 정확한 이름은 G0ARBPR 이다.

첫번째로 Slot Enable이다.

vadcG->ARBPR.U |= slotEnable << (IFX_VADC_G_ARBPR_ASEN0_OFF + slot); /* enable Slot */

slotEnable 은 True 이므로 1
IFX_VADC_G_ARBPR_ASEN0_OFF은 24
slot 은 1이다. (Queue는 0, Background는 2)

IFX_VADC_G_ARBPR_ASEN0_OFF + slot 은 25
1 << 25 는 0b10000000000000000000000000
32 비트로 표현하면
0000001000000000 
0000000000000000

ASEN1 필드의 값이 1로 바뀌며 Arbitration Slot 1 Enable 된다.

두번째로 우선순위 설정이다.

vadcG->ARBPR.U |= (prio << (slot * 4u));                             /* Set Priority */

AutoScan의 우선순위는 1
1 << (1*4) 로 계산된다.
1 << 4

0000000000000000
0000000000010000

PRIO1 필드의 값이 0x1 으로 바뀐다.

두번째로 확인할 부분은 Gating 초기화이다.

        if ((scanSlot->triggerConfig.triggerSource != IfxVadc_TriggerSource_15))
        {
            IfxVadc_setScanSlotGatingConfig(vadcG, scanSlot->triggerConfig.gatingSource, scanSlot->triggerConfig.gatingMode);
        }
        else
        {
            /* do nothing, handled by trigger settings */
        }
IFX_INLINE void IfxVadc_setScanSlotGatingConfig(Ifx_VADC_G *vadcG, IfxVadc_GatingSource gatingSource, IfxVadc_GatingMode gatingMode)
{
    Ifx_VADC_G_ASCTRL asctrl;
    asctrl.U           = vadcG->ASCTRL.U;
    asctrl.B.GTWC      = 1;
    asctrl.B.GTSEL     = gatingSource;
    vadcG->ASCTRL.U    = asctrl.U;
    vadcG->ASMR.B.ENGT = gatingMode;
}

해당 초기화는 asctrl 레지스터를 초기화하는것 같다.

Autoscan Source Control Register이다.

먼저 GTWC 필드를 1로 바꾼다.

GTSEL 필드를 수정하기 위함이다.

GTSEL은 Gate 인풋 소스를 넣는거 같다.
비록 Always 모드 이지만 IfxVadc_GatingSource_0 라고 설정되어있는데 값이 0 이다.

다음으로는 ASMR 레지스터의 ENGT 필드를 수정한다.

IfxVadc_GatingMode_always의 값은 1이다.

디버깅

디버거를 통해 Group의 초기화가 잘되었는지 확인해보겠다.

참조

https://cafe.naver.com/binaryembedded

profile
공부한거 정리, 잘못된 정보 태클은 언제나 환영입니다.

0개의 댓글