This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

C2000WARE: C2000Ware 26.00.00.00 SysConfig: SysCtl_setEMIF1ClockDivider() generated with raw integer instead of enum (F2838x)

Part Number: C2000WARE
Other Parts Discussed in Thread: TMS320F28388D, , SYSCONFIG

Device: TMS320F28388D (F2838x) C2000Ware version: 26.00.00.00 SysConfig version: 1.27.0 CCS version: 20.5.0 (CCS Theia)


Problem Description

When using SysConfig to configure the clock tree on an F2838x device with EMIF1 clock divider set to /2, the generated device.c contains a raw integer instead of the correct enum value:

// Generated (wrong):
SysCtl_setEMIF1ClockDivider(2);

// Expected (correct):
SysCtl_setEMIF1ClockDivider(SYSCTL_EMIF1CLK_DIV_2);

Note that EMIF2 on the same line is generated correctly:

SysCtl_setEMIF2ClockDivider(SYSCTL_EMIF2CLK_DIV_2);  // correct

Why this is harmful: SysCtl_setEMIF1ClockDivider() does not treat its argument as a raw divider value. It checks if(divider == SYSCTL_EMIF1CLK_DIV_2), where SYSCTL_EMIF1CLK_DIV_2 = 1 (enum value). Passing 2 instead of 1 causes the condition to evaluate false, and EMIF1 is silently configured with divider /1 instead of /2 — running the peripheral at twice the intended clock speed.


Root Cause

The bug is in:

driverlib/.meta/device/functions_c/Clocktree/Asserts.xdt

This is the template actually used for F2838x (via Clocktree/Device_clocktree_c.xdt). Note: the top-level device/functions_c/Device_clocktree_c.xdt is not used for this device and is a red herring.

Line 110 stores the full enum string in the fallback case:

%var DEVICE_CLK_EMIF1_DIV = "SYSCTL_EMIF1CLK_DIV_1";

Line 114 stores only the raw integer in the configured case:

%var DEVICE_CLK_EMIF1_DIV = system.clockTree.EMIF1CLKDIV.divideValue;

Line 216 outputs the variable without an enum prefix:

SysCtl_setEMIF1ClockDivider(`DEVICE_CLK_EMIF1_DIV`);

Compare with EMIF2 at line 217, which correctly adds the prefix:

SysCtl_setEMIF2ClockDivider(SYSCTL_EMIF2CLK_DIV_`DEVICE_CLK_EMIF2_DIV`);

Required Fix

Two changes in driverlib/.meta/device/functions_c/Clocktree/Asserts.xdt:

Change 1 — line 110, make the fallback consistent with the prefix pattern:

// Before:
%var DEVICE_CLK_EMIF1_DIV = "SYSCTL_EMIF1CLK_DIV_1";
// After:
%var DEVICE_CLK_EMIF1_DIV = "1";

Change 2 — line 216, add the enum prefix to match the EMIF2 pattern on line 217:

// Before:
    SysCtl_setEMIF1ClockDivider(`DEVICE_CLK_EMIF1_DIV`);
// After:
    SysCtl_setEMIF1ClockDivider(SYSCTL_EMIF1CLK_DIV_`DEVICE_CLK_EMIF1_DIV`);

After both changes, SysConfig correctly generates SysCtl_setEMIF1ClockDivider(SYSCTL_EMIF1CLK_DIV_2) for a /2 divider configuration.

Additional Note

The same bug exists in the top-level (now unused for F2838x) template:

driverlib/.meta/device/functions_c/Device_clocktree_c.xdt

Lines 29/33:

// Fallback (correct — stores full enum string):
%var DEVICE_CLK_EMIF_DIV = "SYSCTL_EMIF1CLK_DIV_1";

// Configured (wrong — stores raw integer):
%var DEVICE_CLK_EMIF_DIV = system.clockTree.EMIF1CLKDIV.divideValue;

Line 233 outputs without prefix:

SysCtl_setEMIF1ClockDivider(`DEVICE_CLK_EMIF_DIV`);

While this file is not executed for F2838x in C2000Ware 26.00.00.00, it may still be used for other devices (F2837xD, F2807x, F2837xS, F28P65x based on the if condition on line 232). The same fix pattern applies: store "1" in the fallback and add the SYSCTL_EMIF1CLK_DIV_ prefix on line 233.