이전 장에서는 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의 초기화가 잘되었는지 확인해보겠다.

