LP-AM243: HOW TO MAKE EDS WORK WITH 16 BITS

Part Number: LP-AM243

Tool/software:

Hi  I can make 8 analog input work with 8 bit , but I tried 16 bits have some problem.

/*
 * app_generic_device.c
 *
 * Generic device profile declarations.
 * LED behavior unchanged: 0x0308 is LED index (1..8) → one LED on.
 * Analogs are 16-bit at 0x0300..0x0307 (scaled 0..32767).
 */

#include "osal.h"
#include "osal_error.h"

#include "drivers/CUST_drivers.h"

#include "EI_API.h"
#include "EI_API_def.h"

#include "appLed.h"
#include "app8AI.h"
#include "appNV.h"
#include "appCfg.h"
#include <device_profiles/app_device_profile.h>
#include <device_profiles/app_device_profile_intern.h>
#include <device_profiles/generic_device/app_generic_device_cfg.h>
#include <device_profiles/generic_device/app_generic_device.h>

static uint16_t EI_APP_GENERIC_DEVICE_extendedStatus_s[255] = {0};

static bool EI_APP_GENERIC_DEVICE_init               (EI_API_ADP_T *pAdapter, EI_API_CIP_NODE_T *pCipNode);
static void EI_APP_GENERIC_DEVICE_run                (EI_API_CIP_NODE_T *pCipNode);
static bool EI_APP_GENERIC_DEVICE_cipSetup           (EI_API_CIP_NODE_T *pCipNode);
static void EI_APP_GENERIC_DEVICE_cipGenerateContent (EI_API_CIP_NODE_T *pCipNode, uint16_t classId, uint16_t instanceId);

/* Boot default: one LED ON (index = 1 => LED0 bit) */
static const uint8_t kBootLedIndex = 1;

/* Track class-1 (scanner) connection state (optional, not required for LED) */
static volatile bool s_cnxOpen = false;

/* ---------------- Connection Manager callback ---------------- */
EI_API_ADP_SEipStatus_t EI_APP_GENERIC_DEVICE_cmgrCb(uint32_t serviceCode, EI_API_ADP_UCmgrInfo_u cmgrInfo)
{
    (void)cmgrInfo;
    EI_API_ADP_SEipStatus_t ret_val = {
        .gen_status = 0,
        .extended_status_size = 0,
        .extended_status_arr = EI_APP_GENERIC_DEVICE_extendedStatus_s
    };

    switch (serviceCode)
    {
        case 0x54: /* Forward Open       */ s_cnxOpen = true;  break;
        case 0x5b: /* Large Forward Open */ s_cnxOpen = true;  break;
        case 0x4e: /* Forward Close      */ s_cnxOpen = false; break;
        default:
            OSAL_printf("unknown service code %x\r\n", serviceCode);
            break;
    }
    return ret_val;
}

/* ---------------- Register profile ---------------- */
uint32_t EI_APP_DEVICE_PROFILE_register(EI_APP_DEVICE_PROFILE_Interface_t *pIntf)
{
    uint32_t error = EI_APP_DEVICE_PROFILE_ERR_General;

    if (NULL == pIntf)
    {
        error = EI_APP_DEVICE_PROFILE_ERR_PtrInvalid;
        goto laError;
    }

    pIntf->task.init = EI_APP_GENERIC_DEVICE_init;
    pIntf->task.run  = EI_APP_GENERIC_DEVICE_run;

    pIntf->cfg.init                  = EI_APP_GENERIC_DEVICE_CFG_init;
    pIntf->cfg.isValid               = EI_APP_GENERIC_DEVICE_CFG_isValid;
    pIntf->cfg.setHeader             = EI_APP_GENERIC_DEVICE_CFG_setHeader;
    pIntf->cfg.apply                 = EI_APP_GENERIC_DEVICE_CFG_apply;
    pIntf->cfg.setDefaultWithoutComm = EI_APP_GENERIC_DEVICE_CFG_setDefaultWithoutComm;
    pIntf->cfg.callback              = EI_APP_GENERIC_DEVICE_CFG_callback;
    pIntf->cfg.getRuntimeData        = EI_APP_GENERIC_DEVICE_CFG_getRuntimeData;
    pIntf->cfg.getFactoryResetData   = EI_APP_GENERIC_DEVICE_CFG_getFactoryResetData;
    pIntf->cfg.getLength             = EI_APP_GENERIC_DEVICE_CFG_getLength;

    error = EI_APP_DEVICE_PROFILE_ERR_OK;

laError:
    return error;
}

/* ---------------- Init ----------------
 * - Build class/instance/attributes/assemblies
 * - Seed 0x0308 = 1 and light one LED so power-up shows LED ON
 */
bool EI_APP_GENERIC_DEVICE_init(EI_API_ADP_T *pAdapter, EI_API_CIP_NODE_T *pCipNode)
{
    (void)pAdapter;

    if (!EI_APP_GENERIC_DEVICE_cipSetup(pCipNode))
        return false;

    /* Initialize LED attribute and hardware (keep same address/semantics) */
    (void)EI_API_CIP_setAttr_usint(pCipNode, 0x0070, 0x0001, 0x0308, kBootLedIndex);
    /* Convert index 1..8 → single-bit mask */
    if (kBootLedIndex >= 1 && kBootLedIndex <= 8)
        EI_APP_LED_industrialSet((uint16_t)(1U << (kBootLedIndex - 1U)));
    else
        EI_APP_LED_industrialSet(0x0001U);

    return true;
}

/* ---------------- Run (cyclic) ----------------
 * Produce: 0x300..0x307 (8 × UINT16, 0..32767 from 0..5000 mV)
 * Consume: 0x308 (USINT LED index 1..8) → light exactly one LED
 */
void EI_APP_GENERIC_DEVICE_run(EI_API_CIP_NODE_T *pCipNode)
{
    /* ----- 8 analog inputs as UINT (0..32767) ----- */
    for (uint16_t ch = 0; ch < 8; ch++)
    {
        uint32_t mv = 0; /* millivolts */
        EI_APP_8AI_industrialGet(ch, &mv);
        if (mv > 5000U) mv = 5000U;

        /* 0..5000 mV → 0..32767 */
        uint16_t scaled = (uint16_t)((mv * 32767U) / 5000U);

        (void)EI_API_CIP_setAttr_uint(pCipNode, 0x0070, 0x0001,
                                      (uint16_t)(0x0300U + ch), scaled);
    }

    /* ----- LED index at 0x308 (keep exact semantics/addr) ----- */
    uint8_t ledIndex = kBootLedIndex; /* default if read fails or out-of-range */
    if (EI_API_CIP_getAttr_usint(pCipNode, 0x0070, 0x0001, 0x0308, &ledIndex) != EI_API_CIP_eERR_OK)
    {
        ledIndex = kBootLedIndex;
    }
    if (ledIndex < 1 || ledIndex > 8)
    {
        ledIndex = kBootLedIndex;
    }

    EI_APP_LED_industrialSet((uint16_t)(1U << (ledIndex - 1U)));
}

/* ---------------- CIP setup ----------------
 * Matches EDS:
 *  - Class 0x70, Instance 0x01
 *  - 0x300..0x307 : UINT (GET)  → Producing/Input (assembly 0x65)
 *  - 0x308..0x30C : USINT (GET&SET) → Consuming/Output (assembly 0x64)
 */
static bool EI_APP_GENERIC_DEVICE_cipSetup(EI_API_CIP_NODE_T *pCipNode)
{
    const uint16_t classId    = 0x0070;
    const uint16_t instanceId = 0x0001;

    EI_APP_GENERIC_DEVICE_cipGenerateContent(pCipNode, classId, instanceId);

    /* Optional */
    (void)EI_API_CIP_createAssembly(pCipNode, 0x00FE, EI_API_CIP_eAR_GET);
    (void)EI_API_CIP_createAssembly(pCipNode, 0x00FF, EI_API_CIP_eAR_GET);

    /* Create assemblies with matching roles */
    (void)EI_API_CIP_createAssembly(pCipNode, 0x0065, EI_API_CIP_eAR_GET);           /* Producing / Input (T→O) */
    (void)EI_API_CIP_createAssembly(pCipNode, 0x0064, EI_API_CIP_eAR_GET_AND_SET);   /* Consuming / Output (O→T) */

    /* Assembly 0x65: inputs 0x300..0x307 (8 × UINT) */
    for (uint16_t attr = 0x0300; attr < 0x0308; attr++)
    {
        uint32_t ec = EI_API_CIP_addAssemblyMember(pCipNode, 0x0065, classId, instanceId, attr);
        if (ec != EI_API_CIP_eERR_OK)
            OSAL_printf("Add member 0x%04X to asm 0x65 failed: 0x%08X\r\n", attr, ec);
    }

    /* Assembly 0x64: outputs 0x308..0x30C (5 × USINT) */
    for (uint16_t attr = 0x0308; attr <= 0x030C; attr++)
    {
        uint32_t ec = EI_API_CIP_addAssemblyMember(pCipNode, 0x0064, classId, instanceId, attr);
        if (ec != EI_API_CIP_eERR_OK)
            OSAL_printf("Add member 0x%04X to asm 0x64 failed: 0x%08X\r\n", attr, ec);
    }

    return true;
}

/* ---------------- CIP class/instance/attributes ----------------
 * Only create exactly what the EDS and app use:
 *  - 0x300..0x307 : UINT (GET)
 *  - 0x308..0x30C : USINT (GET&SET) with 0x308 default = 1
 */
static void EI_APP_GENERIC_DEVICE_cipGenerateContent(EI_API_CIP_NODE_T *cipNode,
                                                     uint16_t classId, uint16_t instanceId)
{
    EI_API_CIP_SService_t service;

    (void)EI_API_CIP_createClass(cipNode, classId);

    service.getAttrAllResponseCnt = 0;
    service.callback = NULL;

    service.code = EI_API_CIP_eSC_GETATTRSINGLE; (void)EI_API_CIP_addClassService(cipNode, classId, &service);
    service.code = EI_API_CIP_eSC_SETATTRSINGLE; (void)EI_API_CIP_addClassService(cipNode, classId, &service);

    (void)EI_API_CIP_createInstance(cipNode, classId, instanceId);

    service.code = EI_API_CIP_eSC_GETATTRSINGLE; (void)EI_API_CIP_addInstanceService(cipNode, classId, instanceId, &service);
    service.code = EI_API_CIP_eSC_SETATTRSINGLE; (void)EI_API_CIP_addInstanceService(cipNode, classId, instanceId, &service);

    /* 0x300..0x307 : UINT (GET) */
    for (uint16_t attrId = 0x0300; attrId < 0x0308; attrId++)
    {
        EI_API_CIP_SAttr_t a;
        OSAL_MEMORY_memset(&a, 0, sizeof(a));
        a.id         = attrId;
        a.edt        = EI_API_CIP_eEDT_UINT;    /* 16-bit */
        a.accessRule = EI_API_CIP_eAR_GET;      /* produced only */
        a.pvValue    = OSAL_MEMORY_calloc(1, sizeof(uint16_t));
        if (!a.pvValue) OSAL_printf("calloc failed for AI attr 0x%04X\r\n", attrId);
        (void)EI_API_CIP_addInstanceAttr(cipNode, classId, instanceId, &a);
    }

    /* 0x308..0x30C : USINT (GET&SET) → outputs/LEDs */
    for (uint16_t attrId = 0x0308; attrId <= 0x030C; attrId++)
    {
        EI_API_CIP_SAttr_t a;
        OSAL_MEMORY_memset(&a, 0, sizeof(a));
        a.id         = attrId;
        a.edt        = EI_API_CIP_eEDT_USINT;           /* 8-bit */
        a.accessRule = EI_API_CIP_eAR_GET_AND_SET;      /* consumed */
        a.pvValue    = OSAL_MEMORY_calloc(1, sizeof(uint8_t));
        if (!a.pvValue)
        {
            OSAL_printf("calloc failed for OUT attr 0x%04X\r\n", attrId);
        }
        else if (attrId == 0x0308)
        {
            /* Default LED index = 1 so one LED is on at boot */
            *((uint8_t*)a.pvValue) = kBootLedIndex;
        }
        (void)EI_API_CIP_addInstanceAttr(cipNode, classId, instanceId, &a);
        if (attrId == 0x0308)
        {
            (void)EI_API_CIP_setInstanceAttr(cipNode, classId, instanceId, &a);
        }
    }
}
/*
 * app8AI.c
 *
 *  Created on: Jul 20, 2025
 *      Author: Thien Tran
 */


#include <stdbool.h>
#include <stdint.h>

#include "osal_error.h"

#include "ti_board_open_close.h"
#include "board/led.h"

#include "app8AI.h"
#include "appMutex.h"

typedef struct EI_APP8AI_Industrial
{
    uint32_t   instance;
    uint32_t   value[8];
}EI_APP8AI_Industrial_t;

/* Global variables and objects */
static HwiP_Object gAdcHwiObject;
static SemaphoreP_Object gAdcSyncSemObject;

/* Function prototypes */
static void App_adcISR(void *handle);
static void App_adcInit(uint32_t baseAddr);
static void App_adcConfig(uint32_t baseAddr);
static void App_adcStart(uint32_t baseAddr);
static void App_adcStop(uint32_t baseAddr);
static void App_adcDeInit(uint32_t baseAddr);

static EI_APP8AI_Industrial_t EI_APP_8AI_industrial_s;

void App_adcISR(void *handle)
{
    uint32_t status;
    uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR;

    /* Get interrupt status and clear */
    status = ADCGetIntrStatus(baseAddr);
    ADCClearIntrStatus(baseAddr, status);

    /* Process ISR */
    SemaphoreP_post(&gAdcSyncSemObject);

    /* Set EOI to generate next interrupt if any */
    ADCWriteEOI(baseAddr);
}

void App_adcConfig(uint32_t baseAddr)
{
    int32_t         configStatus;
    uint32_t        chCnt, adcStep;
    adcStepConfig_t adcConfig;

    /* Enable interrupts */
    ADCEnableIntr(baseAddr, (ADC_INTR_SRC_END_OF_SEQUENCE |
                             ADC_INTR_SRC_FIFO0_THRESHOLD |
                             ADC_INTR_SRC_FIFO0_OVERRUN |
                             ADC_INTR_SRC_FIFO0_UNDERFLOW |
                             ADC_INTR_SRC_FIFO1_THRESHOLD |
                             ADC_INTR_SRC_FIFO1_OVERRUN |
                             ADC_INTR_SRC_FIFO1_UNDERFLOW |
                             ADC_INTR_SRC_OUT_OF_RANGE));

    /*
     * Configure all ADC Steps
     */
    /* Initialize ADC configuration params */
    adcConfig.mode             = ADC_OPERATION_MODE_SINGLE_SHOT;
    adcConfig.openDelay        = 0x1U;
    adcConfig.sampleDelay      = 0U;
    adcConfig.rangeCheckEnable = 0U;
    adcConfig.averaging        = ADC_AVERAGING_16_SAMPLES;
    adcConfig.fifoNum          = ADC_FIFO_NUM_0;

    /* Configure all required steps - Step 1 to N mapped to Channel 1 to N */
    for(chCnt = 0U; chCnt < APP_ADC_NUM_CH; chCnt++)
    {
        adcConfig.channel = ADC_CHANNEL_1 + chCnt;
        adcStep = ADC_STEP_1 + chCnt;   /* Step -> Channel one to one mapped */
        configStatus = ADCSetStepParams(baseAddr, adcStep, &adcConfig);
        DebugP_assert(SystemP_SUCCESS == configStatus);
    }

    ADCStepIdTagEnable(baseAddr, TRUE);
    configStatus = ADCSetCPUFIFOThresholdLevel(baseAddr, ADC_FIFO_NUM_0, 40U);
    DebugP_assert(SystemP_SUCCESS == configStatus);

    /* Step enable */
    for(chCnt = 0U; chCnt < APP_ADC_NUM_CH; chCnt++)
    {
        adcStep = ADC_STEP_1 + chCnt;   /* Step -> Channel one to one mapped */
        ADCStepEnable(baseAddr, adcStep, TRUE);
    }
}

static void App_adcInit(uint32_t baseAddr)
{
    /* Clear All interrupt status */
    ADCClearIntrStatus(baseAddr, ADC_INTR_STATUS_ALL);

    /* Power up AFE */
    ADCPowerUp(baseAddr, TRUE);

    /* Wait for 4us at least */
    ClockP_usleep(5U);

    /* Do the internal calibration */
    ADCInit(baseAddr, FALSE, 0U, 0U);
}

static void App_adcStart(uint32_t baseAddr)
{
    adcSequencerStatus_t status;

    /* Check if FSM is idle */
    ADCGetSequencerStatus(baseAddr, &status);
    while ((ADC_ADCSTAT_FSM_BUSY_IDLE != status.fsmBusy) &&
           ADC_ADCSTAT_STEP_ID_IDLE != status.stepId)
    {
        ADCGetSequencerStatus(baseAddr, &status);
    }
    /* Start ADC conversion */
    ADCStart(baseAddr, TRUE);
}

static void App_adcStop(uint32_t baseAddr)
{
    uint32_t                chCnt, adcStep;
    adcSequencerStatus_t    status;

    /* Disable all/enabled steps */
    for(chCnt = 0U; chCnt < APP_ADC_NUM_CH; chCnt++)
    {
        adcStep = ADC_STEP_1 + chCnt;   /* Step -> Channel one to one mapped */
        ADCStepEnable(baseAddr, adcStep, FALSE);
    }

    /* Wait for FSM to go IDLE */
    ADCGetSequencerStatus(baseAddr, &status);
    while((ADC_ADCSTAT_FSM_BUSY_IDLE != status.fsmBusy) &&
           ADC_ADCSTAT_STEP_ID_IDLE  != status.stepId)
    {
        ADCGetSequencerStatus(baseAddr, &status);
    }

    /* Stop ADC */
    ADCStart(baseAddr, FALSE);

    /* Wait for FSM to go IDLE */
    ADCGetSequencerStatus(baseAddr, &status);
    while ((ADC_ADCSTAT_FSM_BUSY_IDLE != status.fsmBusy) &&
            ADC_ADCSTAT_STEP_ID_IDLE  != status.stepId)
    {
        ADCGetSequencerStatus(baseAddr, &status);
    }
}

static void App_adcDeInit(uint32_t baseAddr)
{
    ADCPowerUp(baseAddr, FALSE);
}

/*!
*
*  \brief
*  Initialize application LED's.
*
*  \param[in]  LED initialization parameters.
*
*  \return     error code as uint32_t
*
*  \retval     #OSAL_NO_ERROR               Success.
*  \retval     #OSAL_GENERAL_ERROR          Negative default value.
*  \retval     #OSAL_LED_DRV_HANDLE_INVALID LED handle is NULL.
*  \retval     #OSAL_LED_DRV_GETATTR        LED_getAttrs call returns NULL.
*  \retval     #OSAL_LED_DRV_SETMASK        LED_setMask call failed.
*
*/
uint32_t EI_APP_8AI_init(EI_APP_8AI_SInit_t* pParams)
{
    uint32_t   result = (uint32_t) OSAL_GENERAL_ERROR;
    uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR;
    HwiP_Params hwiPrms;
    int32_t    status = SystemP_FAILURE;

    // Initialize industrial 8AI's object
    EI_APP_8AI_industrial_s.instance = pParams->industrial8AIsInst;
    for (uint32_t i = 0; i < APP_ADC_NUM_CH; i++){
        EI_APP_8AI_industrial_s.value[i] = 0;
    }

    status = SemaphoreP_constructBinary(&gAdcSyncSemObject, 0);
    DebugP_assert(SystemP_SUCCESS == status);

    /* Register & enable interrupt */
    HwiP_Params_init(&hwiPrms);
    hwiPrms.intNum = CONFIG_ADC0_INTR;
    hwiPrms.callback = &App_adcISR;
    hwiPrms.priority = 1U;
    status = HwiP_construct(&gAdcHwiObject, &hwiPrms);
    DebugP_assert(SystemP_SUCCESS == status);

    /* Initialize, Configure and Start the ADC module */
    App_adcInit(baseAddr);

    result = OSAL_NO_ERROR;
    goto laError;

laError:
    return result;
}

/*!
*
*  \brief
*  De-initialize application LED's.
*
*  \return     error code as uint32_t
*
*  \retval     #OSAL_NO_ERROR               Success.
*  \retval     #OSAL_GENERAL_ERROR          Negative default value.
*  \retval     #OSAL_LED_DRV_HANDLE_INVALID LED handle is NULL.
*  \retval     #OSAL_LED_DRV_SETMASK        LED_setMask call failed.
*
*/
uint32_t EI_APP_8AI_deInit(void)
{
    uint32_t   result = (uint32_t) OSAL_GENERAL_ERROR;
    uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR;

    /* Stop and power down the ADC*/
    App_adcStop(baseAddr);
    App_adcDeInit(baseAddr);

    HwiP_destruct(&gAdcHwiObject);
    SemaphoreP_destruct(&gAdcSyncSemObject);

    result = OSAL_NO_ERROR;
    goto laError;

laError:
    return result;
}

/*!
*
*  \brief
*  Set industrial LEDs controlled by TPIC2810
*
*  \param[in]  pattern             LED pattern.
*
*/
void EI_APP_8AI_industrialGet (uint32_t channel, uint32_t *value)
{
    uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR;
    uint32_t loopcnt, fifoData, fifoWordCnt, stepID, voltageLvl[APP_ADC_NUM_CH];

    App_adcConfig(baseAddr);
    App_adcStart(baseAddr);

    /* Wait for the interrupt to occur */
    SemaphoreP_pend(&gAdcSyncSemObject, SystemP_WAIT_FOREVER);

    /* Get FIFO data */
    fifoWordCnt = ADCGetFIFOWordCount(baseAddr, ADC_FIFO_NUM_0);
    for (loopcnt = 0U; loopcnt < fifoWordCnt; loopcnt++)
    {
       fifoData = ADCGetFIFOData(baseAddr, ADC_FIFO_NUM_0);
       stepID   = ((fifoData & ADC_FIFODATA_ADCCHNLID_MASK) >>
                   ADC_FIFODATA_ADCCHNLID_SHIFT);
       fifoData = ((fifoData & ADC_FIFODATA_ADCDATA_MASK) >>
                   ADC_FIFODATA_ADCDATA_SHIFT);
       voltageLvl[loopcnt]  = fifoData * (uint32_t) APP_ADC_REF_VOLTAGE;
       voltageLvl[loopcnt] /= (uint32_t) ADC_GET_RANGE(CONFIG_ADC0_NUM_BITS);
    }

    *value = voltageLvl[channel];
    return;
}

  • $ EZ-EDS Version 3.34.1.20231010 Generated Electronic Data Sheet

    [File]
    DescText = "EtherNet/IP(tm) Adapter am243x-lp freeRTOS";
    CreateDate = 08-19-2021;
    CreateTime = 17:53:35;
    ModDate = 02-29-2024;
    ModTime = 07:00:00;
    Revision = 3.7;
    HomeURL = "www.ti.com";

    [Device]
    VendCode = 806;
    VendName = "Texas Instruments";
    ProdType = 43;
    ProdTypeStr = "Generic Device";
    ProdCode = 24311;
    MajRev = 3;
    MinRev = 7;
    ProdName = "LP-AM243 Generic Device";
    Catalog = "CatNo9218";
    Icon = "ti.ico";
    IconContents =
    "AAABAAEAICAAAAAAIACsAwAAFgAAAIlQTkcNChoKAAAADUlIRFIAAAAgAAAA"
    "IAgGAAAAc3p69AAAAAFzUkdCAK7OHOkAAAAEZ0FNQQAAsY8L/GEFAAAACXBI"
    "WXMAAA7DAAAOwwHHb6hkAAADQUlEQVRYR+1WSS9kURQusyBmNnaGxBghYpbY"
    "CZGQYIWFhUQQiSkWhKUhVhIr/kzPqqhXhlK6KE2V7pL2J26f77j35T3ea0pK"
    "rXzJSb07nfOd7557bzk+8Brcra2Jo4ICcVxUpJtG7bOKCiGnvC9up6fFV4dD"
    "OA32g+woMfEZgfDmpghvbESXWGh+XhwgoMFcZJ6cHFOg4OKi+ET9ICe7ogMr"
    "AlDBk51tCuRrbRWfqf+4uDhGBHJzoxvIDlYEDvFLNeDv7RV/d3aYyM3EhAiM"
    "juqkLvv7xdXgoAgMDYmrgQH+lkORwYqAIgHJQwsL7PibbOMbhfiFvr+ToSYw"
    "hkLGWMSwUwB9KiCAYNgafP/s7mYCrJT8hfHESBGcmzMRUM5OSkuFt6WFnd5M"
    "TnKWnsxMbl+Pj4vjsjLeJszFqXkzgbuVlcdzLw1ZaunpJmdeupSgwEVbm6lf"
    "y8ri+SCg1IkYv0ZGdAWQBch46+pMzpApFIBasovhjIvTs8e6G1JGDpmBQWdC"
    "gnAlJZktJUW44uPZAQjAGeaiquVSBghCgYf9fb3/D13h6DOudSUnWxM4ra7m"
    "ouFJFqbkhzOYOz9fnNbWsrOHvb3HQJQt2uH1dXFSWSk0uieMa2GY52tutibh"
    "LizkCcYFdoaMITnWhWZn+RuPFNpn5eWcDPbcat3TOjHBTa+cseDsDM49eXns"
    "yEcOccZ98kRoGRmWwWEg4O/stCcAqMKxcqAMji7prGO+m94EZBycmuI2ErBb"
    "/yoC/q4uVkEVDwwOjVlh/PfqKjtCoWLreDHBmZYmXFTQql6MPqCUt6bm/wQA"
    "OMQCOECwAzhMTdWJ4VdOtcRFRwdni7nwA38wNxXm3dLSywT8PT38tkNaX3u7"
    "vsDb2MiO4Fx2WcLX1MRzYCDrpbYcej2ux8ZEYHj42UIogaq/3962dapRXUBu"
    "TRZqVBGcmWECh7TXAbol73d3TUFCy8s8ru6Jd8Eh3Y6QV+0tAqpvbNu7ZG7E"
    "Lb1+CIbqVtWu7M2PTqRw0gP09MJBwZ3X18eGAP4JQXp16SB7qHLZ1xcbAsBZ"
    "VRUHVfJDgZgSAM4bGvjIITgUOSkpiS0BILy1JfAK4jGDKrL7Ay/A4fgH+CbX"
    "ULuRjXIAAAAASUVORK5CYII=";

    [Device Classification]
    Class1 = EtherNetIP;

    [Params]
    $ Outputs (LED bytes) stay USINT at 0x0308..0x030C (do not change)
    Param1 =
    0,
    7,"20 70 24 01 31 08 03",
    0x0000,
    0xC6,
    1,
    "Output1",
    "",
    "Output Byte 1",
    ,,0,
    ,,,,
    ,,,,
    ; $ decimal places
    Param2 =
    0,
    7,"20 70 24 01 31 09 03",
    0x0000,
    0xC6,
    1,
    "Output2",
    "",
    "Output Byte 2",
    ,,0,
    ,,,,
    ,,,,
    ;
    Param3 =
    0,
    7,"20 70 24 01 31 0A 03",
    0x0000,
    0xC6,
    1,
    "Output3",
    "",
    "Output Byte 3",
    ,,0,
    ,,,,
    ,,,,
    ;
    Param4 =
    0,
    7,"20 70 24 01 31 0B 03",
    0x0000,
    0xC6,
    1,
    "Output4",
    "",
    "Output Byte 4",
    ,,0,
    ,,,,
    ,,,,
    ;
    Param5 =
    0,
    7,"20 70 24 01 31 0C 03",
    0x0000,
    0xC6,
    1,
    "Output5",
    "",
    "Output Byte 5",
    ,,0,
    ,,,,
    ,,,,
    ;
    $ Reserved params kept for compatibility (no link path)
    Param6 =
    0,
    ,,
    0x0000,
    0xC6,
    1,
    "Output6",
    "",
    "Parameter 6",
    ,,0,
    ,,,,
    ,,,,
    ;
    Param7 =
    0,
    ,,
    0x0000,
    0xC6,
    1,
    "Output7",
    "",
    "Parameter 7",
    ,,0,
    ,,,,
    ,,,,
    ;
    Param8 =
    0,
    ,,
    0x0000,
    0xC6,
    1,
    "Output8",
    "",
    "Parameter 8",
    ,,0,
    ,,,,
    ,,,,
    ;
    Param9 =
    0,
    ,,
    0x0000,
    0xC6,
    1,
    "Output9",
    "",
    "Parameter 9",
    ,,0,
    ,,,,
    ,,,,
    ;
    Param10 =
    0,
    ,,
    0x0000,
    0xC6,
    1,
    "Output10",
    "",
    "Parameter 10",
    ,,0,
    ,,,,
    ,,,,
    ;

    $ Inputs are UINT at 0x0300..0x0307 (8 channels, 16 bytes total; T=>O uses Assembly 0x64 per path)
    Param11 =
    0,
    7,"20 70 24 01 31 00 03",
    0x0000,
    0xC7,
    2,
    "Input1",
    "",
    "Input Word 1",
    ,,0,
    ,,,,
    ,,,,
    ;
    Param12 =
    0,
    7,"20 70 24 01 31 01 03",
    0x0000,
    0xC7,
    2,
    "Input2",
    "",
    "Input Word 2",
    ,,0,
    ,,,,
    ,,,,
    ;
    Param13 =
    0,
    7,"20 70 24 01 31 02 03",
    0x0000,
    0xC7,
    2,
    "Input3",
    "",
    "Input Word 3",
    ,,0,
    ,,,,
    ,,,,
    ;
    Param14 =
    0,
    7,"20 70 24 01 31 03 03",
    0x0000,
    0xC7,
    2,
    "Input4",
    "",
    "Input Word 4",
    ,,0,
    ,,,,
    ,,,,
    ;
    Param15 =
    0,
    7,"20 70 24 01 31 04 03",
    0x0000,
    0xC7,
    2,
    "Input5",
    "",
    "Input Word 5",
    ,,0,
    ,,,,
    ,,,,
    ;
    Param16 =
    0,
    7,"20 70 24 01 31 05 03",
    0x0000,
    0xC7,
    2,
    "Input6",
    "",
    "Input Word 6",
    ,,0,
    ,,,,
    ,,,,
    ;
    Param17 =
    0,
    7,"20 70 24 01 31 06 03",
    0x0000,
    0xC7,
    2,
    "Input7",
    "",
    "Input Word 7",
    ,,0,
    ,,,,
    ,,,,
    ;
    Param18 =
    0,
    7,"20 70 24 01 31 07 03",
    0x0000,
    0xC7,
    2,
    "Input8",
    "",
    "Input Word 8",
    ,,0,
    ,,,,
    ,,,,
    ;

    [Assembly]
    Object_Name = "Assembly Object";
    Object_Class_Code = 0x04;
    MaxInst = 2;
    Number_Of_Static_Instances = 2;
    Max_Number_Of_Dynamic_Instances = 0;

    Assem1 =
    "Producing Assembly (Input Data)",
    ,
    16,
    0x0001,
    ,,
    16,Param11,
    16,Param12,
    16,Param13,
    16,Param14,
    16,Param15,
    16,Param16,
    16,Param17,
    16,Param18;

    Assem2 =
    "Consuming Assembly (Output Data)",
    ,
    5,
    0x0001,
    ,,
    8,Param1,
    8,Param2,
    8,Param3,
    8,Param4,
    8,Param5;

    [Connection Manager]
    Object_Name = "Connection Manager Object";
    Object_Class_Code = 0x06;

    Connection1 =
    0x04010002,
    0x44640005,
    20,5,Assem2, $ O=>T (controller->device): 5 bytes, LEDs
    20,16,Assem1, $ T=>O (device->controller): 16 bytes, inputs
    ,,
    ,,
    "Exclusive Owner",
    "",
    "20 04 24 01 2C 65 2C 64";

    Connection2 =
    0x02010002,
    0x44640305,
    ,0,,
    20,16,Assem1,
    ,,
    ,,
    "Input Only",
    "",
    "20 04 24 01 2C FE 2C 64";

    Connection3 =
    0x01010002,
    0x44640305,
    ,0,,
    20,16,Assem1,
    ,,
    ,,
    "Listen Only",
    "",
    "20 04 24 01 2C FF 2C 64";

    [Capacity]
    MaxCIPConnections = 12;
    MaxConsumersPerMcast = 3;
    TSpec1 = TxRx, 5, 500;

    [DLR Class]
    Revision = 3;
    Object_Name = "Device Level Ring Object";
    Object_Class_Code = 0x47;
    MaxInst = 1;
    Number_Of_Static_Instances = 1;
    Max_Number_Of_Dynamic_Instances = 0;
    Ring_Supervisor_Capable = No;

    [TCP/IP Interface Class]
    Revision = 4;
    Object_Name = "TCP/IP Interface Object";
    Object_Class_Code = 0xF5;
    MaxInst = 1;
    Number_Of_Static_Instances = 1;
    Max_Number_Of_Dynamic_Instances = 0;
    ENetQCT1 =
    4000,
    500;

    [Ethernet Link Class]
    Revision = 4;
    Object_Name = "Ethernet Link Object";
    Object_Class_Code = 0xF6;
    MaxInst = 2;
    Number_Of_Static_Instances = 2;
    Max_Number_Of_Dynamic_Instances = 0;
    InterfaceLabel1 = "Port 1";
    InterfaceLabel2 = "Port 2";

    [Time Sync Class]
    Revision = 4;
    Object_Name = "Time Sync Object";
    Object_Class_Code = 0x43;
    MaxInst = 1;
    Number_Of_Static_Instances = 1;
    Max_Number_Of_Dynamic_Instances = 0;

    [QoS Class]
    Revision = 1;
    Object_Name = "QoS Object";
    Object_Class_Code = 0x48;
    MaxInst = 1;
    Number_Of_Static_Instances = 1;
    Max_Number_Of_Dynamic_Instances = 0;

    [LLDP Management Class]
    Revision = 1;
    Object_Name = "LLDP Management Object";
    Object_Class_Code = 0x109;
    MaxInst = 1;
    Number_Of_Static_Instances = 1;
    Max_Number_Of_Dynamic_Instances = 0;

    [LLDP Data Table Class]
    Revision = 1;
    Object_Name = "LLDP Data Table Object";
    Object_Class_Code = 0x10A;
    MaxInst = 16;
    Number_Of_Static_Instances = 0;
    Max_Number_Of_Dynamic_Instances = 16;

  • Hi Thien,

    I did a review of EDS and your code, I didn't notice any potential problem.
    What is exactly the issue you are facing? Please describe the problem in details.

    Regards,
    Pourya

  • HI Pourya. Do you have any experience with this problems , I read 2 years ago, You did not solve this problem https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1191097/mcu-plus-sdk-am243x-ethernet-ip-not-working-with-16-bit-data-type/4591532

    I test my program if Led run, then my program will run 

    PROGRAM PLC_PRG
    VAR
    (* ---- device inputs (T->O) ---- *)
    usiInput0 : USINT; (* Input1: 8-bit *)
    usiInput1 : USINT; (* Input2: 8-bit *)
    aiWord3 : UINT; (* Input3: 16-bit *)
    aiWord4 : UINT; (* Input4: 16-bit *)
    aiWord5 : UINT; (* Input5: 16-bit *)
    aiWord6 : UINT; (* Input6: 16-bit *)
    aiWord7 : UINT; (* Input7: 16-bit *)
    aiWord8 : UINT; (* Input8: 16-bit *)

    (* ---- controller outputs (O->T) ---- *)
    usiOutput : USINT; (* Output Byte 1 -> LED byte in firmware; SAME as before *)

    (* original LED timing/pattern *)
    iCounter : UDINT;
    i : UDINT;
    tCycle : TIME := T#200ms;
    bToggleOn : BOOL := TRUE;
    bToggleOff : BOOL;
    fbTOn : TON;
    fbTOff : TON;


    (* ===== LED pattern: UNCHANGED ===== *)
    fbTOn(IN := bToggleOn, PT := tCycle/2);
    IF fbTOn.Q THEN
    bToggleOn := FALSE;
    bToggleOff := TRUE;
    END_IF;

    fbTOff(IN := bToggleOff, PT := tCycle/2);
    IF fbTOff.Q THEN
    bToggleOff := FALSE;
    bToggleOn := TRUE;
    iCounter := iCounter + 1;
    END_IF;

    i := TO_USINT(iCounter MOD 8);
    usiOutput := TO_USINT(EXPT(2, i)); (* SAME byte that drives LEDs *)

    (* ===== legacy 8-bit pack: UNCHANGED ===== *)
    GVL.uiVisuOut := SHL(TO_UINT(usiInput1), 8) OR TO_UINT(usiInput0);
    GVL.uiAnalogInput := TO_REAL(GVL.uiVisuOut) * (3.48 + 2.94) / 3.48 / 1000.0;

    (* ===== optional: show one 16-bit channel (Input3) as “analog” ===== *)
    (*GVL.uiVisuOut16 := aiWord3; *)
    (*GVL.uiAnalogInput16 := TO_REAL(GVL.uiVisuOut16) * (3.48 + 2.94) / 3.48 / 1000.0; *)
    (*; *)


    END_VAR

    We spend a week , I can not solve this problem.  You look at the code 

     I really need help. !!!!

  • Hi Thien,

    To better understand the issue, please send us the Wireshark log from the communication between your PLC and your device. Having this log will allow us to clearly identify where the problem might be.

    In the meantime, you can also try setting the attribute access for attribute IDs 0x300 to 0x307 to 'Settable' and 'Gettable' to see if it resolves the issue.

        /* 0x300..0x307 : UINT (GET) */
        for (uint16_t attrId = 0x0300; attrId < 0x0308; attrId++)
        {
            EI_API_CIP_SAttr_t a;
            OSAL_MEMORY_memset(&a, 0, sizeof(a));
            a.id         = attrId;
            a.edt        = EI_API_CIP_eEDT_UINT;    /* 16-bit */
            a.accessRule = EI_API_CIP_eAR_GET_AND_SET;      /* produced only */
            a.pvValue    = OSAL_MEMORY_calloc(1, sizeof(uint16_t));
            if (!a.pvValue) OSAL_printf("calloc failed for AI attr 0x%04X\r\n", attrId);
            (void)EI_API_CIP_addInstanceAttr(cipNode, classId, instanceId, &a);
        }

    Best regards,
    Pourya