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;
}