diff --git a/EnduranceTestBench/.cproject b/EnduranceTestBench/.cproject index 3073a88..c91aa0f 100644 --- a/EnduranceTestBench/.cproject +++ b/EnduranceTestBench/.cproject @@ -71,6 +71,8 @@ + + @@ -126,6 +128,8 @@ + + @@ -159,7 +163,8 @@ - + + @@ -233,6 +238,8 @@ + + @@ -287,6 +294,8 @@ + + @@ -313,10 +322,10 @@ + + - - diff --git a/EnduranceTestBench/.project b/EnduranceTestBench/.project index 9641c51..75885d9 100644 --- a/EnduranceTestBench/.project +++ b/EnduranceTestBench/.project @@ -40,11 +40,25 @@ 2 copy_PARENT/common + + nms_can + 2 + PROJECT_LOC/nms_can + + + nms_hal + 2 + copy_PROJECT_LOC/nms_hal + copy_PARENT $%7BPARENT-3-PROJECT_LOC%7D/Documents/NorthStar-Endurance-TestBench + + copy_PROJECT_LOC + $%7BPARENT-1-copy_PARENT%7D/NorthStar-Production-Unit-Board-Firmware/ProcessBoardV1 + diff --git a/EnduranceTestBench/Core/Src/adc.c b/EnduranceTestBench/Core/Src/adc.c index 3b14772..03575a0 100644 --- a/EnduranceTestBench/Core/Src/adc.c +++ b/EnduranceTestBench/Core/Src/adc.c @@ -51,13 +51,13 @@ void MX_ADC1_Init(void) hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; hadc1.Init.LowPowerAutoWait = DISABLE; - hadc1.Init.ContinuousConvMode = DISABLE; + hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.NbrOfConversion = 1; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.DMAContinuousRequests = DISABLE; - hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED; + hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; hadc1.Init.OversamplingMode = DISABLE; if (HAL_ADC_Init(&hadc1) != HAL_OK) { diff --git a/EnduranceTestBench/Core/Src/main.c b/EnduranceTestBench/Core/Src/main.c index bebc87e..d76251c 100644 --- a/EnduranceTestBench/Core/Src/main.c +++ b/EnduranceTestBench/Core/Src/main.c @@ -78,7 +78,7 @@ int main(void) /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ - HAL_Init(); + HAL_Init(); /* USER CODE BEGIN Init */ diff --git a/EnduranceTestBench/EnduranceTestBench.ioc b/EnduranceTestBench/EnduranceTestBench.ioc index d94d3f7..19d2376 100644 --- a/EnduranceTestBench/EnduranceTestBench.ioc +++ b/EnduranceTestBench/EnduranceTestBench.ioc @@ -1,9 +1,11 @@ #MicroXplorer Configuration settings - do not modify ADC1.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_1 ADC1.CommonPathInternal=null|null|null|null -ADC1.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,OffsetNumber-0\#ChannelRegularConversion,NbrOfConversionFlag,master,CommonPathInternal +ADC1.ContinuousConvMode=ENABLE +ADC1.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,OffsetNumber-0\#ChannelRegularConversion,NbrOfConversionFlag,master,Overrun,ContinuousConvMode,CommonPathInternal ADC1.NbrOfConversionFlag=1 ADC1.OffsetNumber-0\#ChannelRegularConversion=ADC_OFFSET_NONE +ADC1.Overrun=ADC_OVR_DATA_OVERWRITTEN ADC1.Rank-0\#ChannelRegularConversion=1 ADC1.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_2CYCLES_5 ADC1.master=1 @@ -206,8 +208,8 @@ ProjectManager.MainLocation=Core/Src ProjectManager.NoMain=false ProjectManager.PreviousToolchain=STM32CubeIDE ProjectManager.ProjectBuild=false -ProjectManager.ProjectFileName=ProcessBoardV1.ioc -ProjectManager.ProjectName=ProcessBoardV1 +ProjectManager.ProjectFileName=EnduranceTestBench.ioc +ProjectManager.ProjectName=EnduranceTestBench ProjectManager.ProjectStructure= ProjectManager.RegisterCallBack= ProjectManager.StackSize=0x400 diff --git a/EnduranceTestBench/nehemis/analogMeasurement.c b/EnduranceTestBench/nehemis/analogMeasurement.c new file mode 100644 index 0000000..aea7159 --- /dev/null +++ b/EnduranceTestBench/nehemis/analogMeasurement.c @@ -0,0 +1,92 @@ +/** + * @file analogMeasurement.c + * + * @copyright Nehemis SARL reserves all rights even in the event of industrial + * property rights. We reserve all rights of disposal such as + * copying and passing on to third parties. + * + * @brief Source code for ADC data reading module. + */ + +/****************************************************************************** + * Include Header Files + ******************************************************************************/ +#include "analogMeasurement.h" +#include "hal_adc.h" + +/****************************************************************************** + * Macro Constant Declarations + ******************************************************************************/ +#define ADC_BUFFER_SIZE 9u + +/****************************************************************************** + * Module Global Variable Declarations + ******************************************************************************/ +static uint16 adcBuffer_u32[ADC_BUFFER_SIZE]; + +/****************************************************************************** + * Private Function Declarations + ******************************************************************************/ +static void AnalogMeasurementInitBuffer(void); + +/****************************************************************************** + * Function Definitions + ******************************************************************************/ +void AnalogMeasurementInit(void) +{ + uint32 error_u32 = NMS_ERR_DEFAULT; + + AnalogMeasurementInitBuffer(); + + HalAdcCalibrate(MAP_HAL_ADC_1); + error_u32 = HalAdcStartDMA(MAP_HAL_ADC_1, (uint32 *)adcBuffer_u32, ADC_BUFFER_SIZE); + + if (error_u32 != NMS_ERR_NONE) + { + /* Handle the error (DMA start failed) */ + } +} + +void AnalogMesaurementRun(void) +{ + HalAdcStartDMA(MAP_HAL_ADC_1, (uint32 *)adcBuffer_u32, sizeof(adcBuffer_u32)); +} + + +void AnalogMeasurementReadData(uint32 channel_u32, uint32 *adcValue_pu32) +{ + + if (adcValue_pu32 == NULL) + { + return; /* Prevent dereferencing NULL pointer */ + } + __disable_irq(); + switch (channel_u32) + { + case PS1_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[0]; break; + case PS2_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[1]; break; + case PS3_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[2]; break; + case PS4_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[3]; break; + + case PMP_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[4]; break; + + case FM1_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[5]; break; + case FM2_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[6]; break; + case FM3_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[7]; break; + case FM4_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[8]; break; + default: *adcValue_pu32 = 0uL; break; + } + __enable_irq(); +} + +/****************************************************************************** + * Private Function Definitions + ******************************************************************************/ +/* @brief Initialize buffer with default values*/ +static void AnalogMeasurementInitBuffer(void) +{ + for (uint8 i_u8 = 0u; i_u8 < ADC_BUFFER_SIZE; i_u8++) + { + adcBuffer_u32[i_u8] = 0uL; + } +} diff --git a/EnduranceTestBench/nehemis/analogMeasurement.h b/EnduranceTestBench/nehemis/analogMeasurement.h new file mode 100644 index 0000000..14d4db0 --- /dev/null +++ b/EnduranceTestBench/nehemis/analogMeasurement.h @@ -0,0 +1,53 @@ +/** + * @file analogMeasurement.h + * + * @copyright Nehemis SARL reserves all rights even in the event of industrial + * property rights. We reserve all rights of disposal such as + * copying and passing on to third parties. + * + * @brief ADC measurement module interface. + * This file provides function declarations and necessary definitions + * for reading analog sensor values using ADC with DMA. It defines + * ADC channel mappings, reference voltage, and resolution to ensure + * consistent data acquisition across multiple modules. + * + */ +#ifndef ANALOGMEASUREMENT_H_ +#define ANALOGMEASUREMENT_H_ + +/****************************************************************************** + * Include Header Files + ******************************************************************************/ +#include "nms_types.h" +/****************************************************************************** + * Type declarations + ******************************************************************************/ +#define PS1_ADC_CHANNEL 1u +#define PS2_ADC_CHANNEL 2u +#define PS3_ADC_CHANNEL 3u +#define PS4_ADC_CHANNEL 4u +#define PMP_ADC_CHANNEL 5u +#define FM1_ADC_CHANNEL 6u +#define FM2_ADC_CHANNEL 7u +#define FM3_ADC_CHANNEL 8u +#define FM4_ADC_CHANNEL 9u + +#define ANALOG_MEAS_ADC_REF_VOLTAGE 3.3f +#define ANALOG_MEAS_ADC_RESOLUTION 4095.0f /* 12-bit ADC */ +/****************************************************************************** + * Extern Function Declarations + ******************************************************************************/ +/* @brief initialize the ADC, calibrate and Start the ADC in DMA mode */ +void AnalogMeasurementInit(void); + +void AnalogMesaurementRun(void); + +/** + * @brief Reads the latest ADC value for the specified channel. + * + * @param channel_u32 The ADC channel to read from. + * adcValue Pointer to store the retrieved ADC value. + */ +void AnalogMeasurementReadData(uint32 channel_u32, uint32 * adcValue_pu32); + +#endif /* ANALOGMEASUREMENT_H_ */ diff --git a/EnduranceTestBench/nehemis/appl.h b/EnduranceTestBench/nehemis/appl.h new file mode 100644 index 0000000..dbe430f --- /dev/null +++ b/EnduranceTestBench/nehemis/appl.h @@ -0,0 +1,42 @@ +#include "nms_types.h" + +extern char string1[]; +extern char string2[]; + +extern OCTET_STRING octet1[]; +extern OCTET_STRING octet2[]; + +extern CO_DOMAIN_PTR pDomain1; +extern CO_DOMAIN_PTR pDomain2; + +#ifdef xxx +RET_T sdoServInd(CO_LINE_TYPE, BOOL_T, UNSIGNED8, UNSIGNED16, UNSIGNED8); +RET_T sdoServWrInd(CO_LINE_TYPE, BOOL_T, UNSIGNED8, UNSIGNED16, UNSIGNED8); +RET_T sdoServChkInd(CO_LINE_TYPE, BOOL_T, UNSIGNED8, UNSIGNED16, UNSIGNED8, const UNSIGNED8 *); +void errCtrl(CO_LINE_DECL, UNSIGNED8, CO_ERRCTRL_T, CO_NMT_STATE_T); +RET_T nmtInd(CO_LINE_DECL, BOOL_T, CO_NMT_STATE_T); +void pdoInd(CO_LINE_TYPE, UNSIGNED16); +void pdoRecInd(CO_LINE_TYPE, UNSIGNED16); +void pdoSyncInd(CO_LINE_TYPE, UNSIGNED16); +void syncInd(CO_LINE_TYPE); +void syncFinishedInd(CO_LINE_TYPE); +void ledRedInd(CO_LINE_TYPE, BOOL_T); +void ledGreenInd(CO_LINE_TYPE, BOOL_T); +void canInd(CO_LINE_TYPE, CO_CAN_STATE_T); +void commInd(CO_LINE_TYPE, CO_COMM_STATE_EVENT_T); +void sdoClRd(CO_LINE_TYPE, UNSIGNED8, UNSIGNED16, UNSIGNED8, UNSIGNED32, UNSIGNED32); +void sdoClWr(CO_LINE_TYPE, UNSIGNED8, UNSIGNED16, UNSIGNED8, UNSIGNED32); +void sdoQuInd(CO_LINE_TYPE, void *pData, UNSIGNED32 result); +RET_T emcyInd(CO_LINE_TYPE, UNSIGNED16 errCode, const UNSIGNED8 *addErrorCode); +void emcyConsInd(CO_LINE_TYPE, UNSIGNED8 node, UNSIGNED16 errCode, UNSIGNED8 errorRegister, UNSIGNED8 const *addErrorCode); +void timeInd(CO_LINE_TYPE, CO_TIME_T *pTime); +RET_T storeInd(CO_LINE_DECL, UNSIGNED8 subIndex); +#endif + + +void sdoClientReadInd(UNSIGNED8 canLine, UNSIGNED8 sdoNr, UNSIGNED16 index, + UNSIGNED8 subIndex, UNSIGNED32 size, UNSIGNED32 result); +void sdoClientWriteInd(UNSIGNED8 canLine, UNSIGNED8 sdoNr, + UNSIGNED16 index, UNSIGNED8 subIndex, UNSIGNED32 result); + +uint8 getMyNodeId(CO_LINE_DECL); diff --git a/EnduranceTestBench/nehemis/enduranceTestBench.c b/EnduranceTestBench/nehemis/enduranceTestBench.c index 425d3a7..fe74149 100644 --- a/EnduranceTestBench/nehemis/enduranceTestBench.c +++ b/EnduranceTestBench/nehemis/enduranceTestBench.c @@ -13,12 +13,12 @@ * Include Header Files ******************************************************************************/ #include "enduranceTestBench.h" -#include "hal_system.h" #include "stdlib.h" /* CANopen includes */ #include #include +#include "hal_system.h" /****************************************************************************** * Macro constant declarations diff --git a/EnduranceTestBench/nehemis/flowmeter.c b/EnduranceTestBench/nehemis/flowmeter.c index b0f3ddb..a743cca 100644 --- a/EnduranceTestBench/nehemis/flowmeter.c +++ b/EnduranceTestBench/nehemis/flowmeter.c @@ -14,6 +14,7 @@ ******************************************************************************/ #include "nms_types.h" #include "flowmeter.h" +#include "analogMeasurement.h" /****************************************************************************** * Type declarations @@ -22,38 +23,34 @@ /****************************************************************************** * Macro Constant Declarations ******************************************************************************/ -#define FLOWMETER_ADC_REF_VOLTAGE 3.3f -#define FLOWMETER_ADC_RESOLUTION 4095.0f /* 12-bit ADC */ + /****************************************************************************** * Private function Declarations ******************************************************************************/ -static float32 FlowmeterReadVoltage(FlowmeterMain_st *flowmeter_pst); - +static void FlowmeterReadVoltage(FlowmeterMain_st * flowmeter_pst); +FlowmeterMain_st *flowmeter_gpst; /****************************************************************************** * Extern Function Definitions ******************************************************************************/ -void FlowmeterInit(FlowmeterMain_st *flowmeter_pst, ADC_HandleTypeDef *adcHandle_pst, uint32 channel_u32) +void FlowmeterInit(FlowmeterMain_st *flowmeter_pst) { - if (flowmeter_pst == NULL || adcHandle_pst == NULL) + if (flowmeter_pst == NULL) { /* ERROR */ } - flowmeter_pst->adcHandle_pst = adcHandle_pst; - flowmeter_pst->channel_u32 = channel_u32; flowmeter_pst->mKu_f32 = 5.0f; // Default value } - void FlowmeterGetFlow(FlowmeterMain_st *flowmeter_pst) { if (flowmeter_pst == NULL) { /* ERROR */ } - - flowmeter_pst->rawQ_f32 = flowmeter_pst->mKu_f32 * FlowmeterReadVoltage(flowmeter_pst); + FlowmeterReadVoltage(flowmeter_pst); + flowmeter_pst->rawQ_f32 = flowmeter_pst->mKu_f32 * flowmeter_pst->voltage_f32; } @@ -88,40 +85,11 @@ void FlowmeterSetKu(FlowmeterMain_st *flowmeter_pst, float32 ku_f32) * @return ADC output voltage based on sensor reading. * */ -static float32 FlowmeterReadVoltage(FlowmeterMain_st *flowmeter_pst) +static void FlowmeterReadVoltage(FlowmeterMain_st *flowmeter_pst) { - uint32 adcVal_u32 = 0uL; - if (flowmeter_pst == NULL || flowmeter_pst->adcHandle_pst == NULL) - { - return 0.0f; /* Error Case */ - } - - ADC_ChannelConfTypeDef sConfig = {0}; - sConfig.Channel = flowmeter_pst->channel_u32; /* Set the channel specific to this flowmeter */ - sConfig.Rank = ADC_REGULAR_RANK_1; - sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5; - - if (HAL_ADC_ConfigChannel(flowmeter_pst->adcHandle_pst, &sConfig) != HAL_OK) - { - return 0.0f; /* ERROR */ - } - - /* Start ADC conversion and poll for completion */ - if (HAL_ADC_Start(flowmeter_pst->adcHandle_pst) == HAL_OK) - { - if (HAL_ADC_PollForConversion(flowmeter_pst->adcHandle_pst, HAL_MAX_DELAY) == HAL_OK) - { - adcVal_u32 = HAL_ADC_GetValue(flowmeter_pst->adcHandle_pst); - } - HAL_ADC_Stop(flowmeter_pst->adcHandle_pst); - } - else - { - /* ERROR */ - } - /* Convert ADC value to voltage (assuming 12-bit resolution and 3.3V reference) */ - float32 voltage_f32 = (float)adcVal_u32 * (FLOWMETER_ADC_REF_VOLTAGE / FLOWMETER_ADC_RESOLUTION); + uint32 adcVal_u32 = 0uL; + AnalogMeasurementReadData(flowmeter_pst->channel_u32, &adcVal_u32); - return voltage_f32; + flowmeter_pst->voltage_f32 = (float32)adcVal_u32 * (ANALOG_MEAS_ADC_REF_VOLTAGE / ANALOG_MEAS_ADC_RESOLUTION); } diff --git a/EnduranceTestBench/nehemis/flowmeter.h b/EnduranceTestBench/nehemis/flowmeter.h index eecb209..4431c4c 100644 --- a/EnduranceTestBench/nehemis/flowmeter.h +++ b/EnduranceTestBench/nehemis/flowmeter.h @@ -22,19 +22,16 @@ ******************************************************************************/ typedef struct { - ADC_HandleTypeDef *adcHandle_pst; float32 mKu_f32; uint32 channel_u32; float32 rawQ_f32; + float32 voltage_f32; } FlowmeterMain_st; /* HubaFlowmeter structure definition */ /****************************************************************************** * Macro Constant Declarations ******************************************************************************/ -#define FLOWMETER_FM1_ADC_CHANNEL 6u -#define FLOWMETER_FM2_ADC_CHANNEL 7u -#define FLOWMETER_FM3_ADC_CHANNEL 8u -#define FLOWMETER_FM4_ADC_CHANNEL 9u + /****************************************************************************** * Extern Function Declarations ******************************************************************************/ @@ -42,13 +39,11 @@ typedef struct * @brief Init function of the Flowmeter module. * * @param flowmeter_pst : Pointer to main strucutre of the module. - * adcHandle_pst : ADC handler f the flowmeter. - * channel_u32 : ADC channel of the connected sensor to use. * * @return Flow rate value. * */ -void FlowmeterInit(FlowmeterMain_st *flowmeter_pst, ADC_HandleTypeDef *adcHandle_pst, uint32 channel_u32); +void FlowmeterInit(FlowmeterMain_st *flowmeter_pst); /** * @brief Function to get flow value diff --git a/EnduranceTestBench/nehemis/grundfos.c b/EnduranceTestBench/nehemis/grundfos.c index d9ec135..406e23e 100644 --- a/EnduranceTestBench/nehemis/grundfos.c +++ b/EnduranceTestBench/nehemis/grundfos.c @@ -13,8 +13,9 @@ * Include Header Files ******************************************************************************/ #include "grundfos.h" -#include "gpio.h" -#include "i2c.h" +#include "analogMeasurement.h" +#include "hal_gpio.h" +#include "hal_i2c.h" /****************************************************************************** * Type declarations ******************************************************************************/ @@ -22,40 +23,31 @@ /****************************************************************************** * Macro Constant Declarations ******************************************************************************/ -#define GRUNDFOS_PMP_ADC_CHANNEL 5u -#define GRUNDFOS_PMP_ADC_REF_VOLTAGE 3.3f -#define GRUNDFOS_PMP_ADC_RESOLUTION 4095.0f /* 12-bit ADC */ -#define GRUNDFOS_PMP_ADC_MODULE &hadc1 - -#define GRUNDFOS_PMP_ENABLE_GPIO_PORT GPIOB -#define GRUNDFOS_PMP_ENABLE_GPIO_PIN GPIO_PIN_15 - -#define GRUNDFOS_PMP_I2C_HANDLE &hi2c4 -#define GRUNDFOS_PMP_INTERNAL_DAC_ADDR 0x61 +#define GRUNDFOS_PMP_INTERNAL_DAC_ADDR (0x61 << 1) /****************************************************************************** * Private function Declarations ******************************************************************************/ -static uint32 GrundfosPmpReadVoltage(void); +static uint32 GrundfosPmpReadVoltage(uint8 channel_u8); /****************************************************************************** * Extern Function Definitions ******************************************************************************/ void GrundfosPmpEnable(uint8 state_u8) { - if(state_u8 == 1u) + if(state_u8 == 0u) { - HAL_GPIO_WritePin(GRUNDFOS_PMP_ENABLE_GPIO_PORT, GRUNDFOS_PMP_ENABLE_GPIO_PIN, GPIO_PIN_SET); + HalGpioWrite(MAP_HAL_PMP_ENABLE, HAL_GPIO_STATE_HIGH); /* Pulling the line high stops the pump */ } else { - HAL_GPIO_WritePin(GRUNDFOS_PMP_ENABLE_GPIO_PORT, GRUNDFOS_PMP_ENABLE_GPIO_PIN, GPIO_PIN_RESET); + HalGpioWrite(MAP_HAL_PMP_ENABLE, HAL_GPIO_STATE_LOW); } } -uint32 GrundfosPmpFeedbackSpeed(void) +uint32 GrundfosPmpFeedbackSpeed(uint8 channel_u8) { - uint32 feedbackSpeed_u32 = (GrundfosPmpReadVoltage()) * 360uL; + uint32 feedbackSpeed_u32 = (GrundfosPmpReadVoltage(channel_u8)) * 360uL; return feedbackSpeed_u32; } @@ -64,29 +56,31 @@ uint32 GrundfosPmpFeedbackSpeed(void) bool GrundfosPmpSetSpeed(float32 setSpeed_f32) { uint8 data_au8[2]; - uint16 dacVal_u16; + static volatile uint16 dacVal_u16 = 0u; + /* Limit the input range to 0V - 10V */ if (setSpeed_f32 < 0.0f) { - setSpeed_f32 = 0.0f; + setSpeed_f32 = 0.0f; } else if (setSpeed_f32 > 10.0f) { - setSpeed_f32 = 10.0f; - } - else - { - /* Do nothing. */ + setSpeed_f32 = 10.0f; } - dacVal_u16 = (uint16)(setSpeed_f32 * (GRUNDFOS_PMP_ADC_RESOLUTION / 10.0f)); + /* Convert pump speed (0-10V) to DAC value (0-5V output) */ + dacVal_u16 = (uint16)((setSpeed_f32 * 4095.0f) / 10.0f); - data_au8[0] = (uint8)(dacVal_u16 >> 4); /* Upper 8 bits */ - data_au8[1] = (uint8)((dacVal_u16 & 0x0F) << 4); /* Lower 4 bits shifted to the upper nibble */ + /* Format the 12-bit DAC value into the correct byte format */ + data_au8[0] = (uint8)(dacVal_u16 >> 8); /* Upper 8 bits */ + data_au8[1] = (uint8)(dacVal_u16 & 0xFF); /* Lower 8 bits */ - return HAL_I2C_Master_Transmit(GRUNDFOS_PMP_I2C_HANDLE, GRUNDFOS_PMP_INTERNAL_DAC_ADDR, data_au8, 2u, HAL_MAX_DELAY) == HAL_OK; + return HalI2CMasterTransmit(MAP_HAL_GRUNDFOS_PMP_I2C_HANDLE, + GRUNDFOS_PMP_INTERNAL_DAC_ADDR, + data_au8, 2u) == NMS_ERR_NONE; } + /****************************************************************************** * Private function Definitions ******************************************************************************/ @@ -96,33 +90,13 @@ bool GrundfosPmpSetSpeed(float32 setSpeed_f32) * @return ADC output voltage based on sensor reading. * */ -static uint32 GrundfosPmpReadVoltage(void) +static uint32 GrundfosPmpReadVoltage(uint8 channel_u8) { - uint32_t adcVal_u32 = 0uL; - ADC_ChannelConfTypeDef sConfig = {0}; - sConfig.Channel = GRUNDFOS_PMP_ADC_CHANNEL; /* Set the channel specific to this flowmeter */ - sConfig.Rank = ADC_REGULAR_RANK_1; - sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5; + /* Convert ADC value to voltage (assuming 12-bit resolution and 3.3V reference) */ + uint32 adcVal_u32 = 0uL; + AnalogMeasurementReadData(channel_u8, &adcVal_u32); + float32 voltage_f32 = (float32)adcVal_u32 * (ANALOG_MEAS_ADC_REF_VOLTAGE / ANALOG_MEAS_ADC_RESOLUTION); - if (HAL_ADC_ConfigChannel(GRUNDFOS_PMP_ADC_MODULE, &sConfig) != HAL_OK) - { - return 0.0f; /* ERROR */ - } - - if (HAL_ADC_Start(GRUNDFOS_PMP_ADC_MODULE) == HAL_OK) - { - if (HAL_ADC_PollForConversion(GRUNDFOS_PMP_ADC_MODULE, HAL_MAX_DELAY) == HAL_OK) - { - adcVal_u32 = HAL_ADC_GetValue(GRUNDFOS_PMP_ADC_MODULE); - } - HAL_ADC_Stop(GRUNDFOS_PMP_ADC_MODULE); - } - else - { - /* ERROR */ - } - - uint32 voltage_u32 = adcVal_u32 * (GRUNDFOS_PMP_ADC_REF_VOLTAGE / GRUNDFOS_PMP_ADC_RESOLUTION); - - return voltage_u32; + return voltage_f32; } + diff --git a/EnduranceTestBench/nehemis/grundfos.h b/EnduranceTestBench/nehemis/grundfos.h index 75a8da7..941a988 100644 --- a/EnduranceTestBench/nehemis/grundfos.h +++ b/EnduranceTestBench/nehemis/grundfos.h @@ -21,6 +21,11 @@ /****************************************************************************** * Type declarations ******************************************************************************/ +typedef struct +{ + uint32 channel_u32; + float32 rawQ_f32; +} GrundfosMain_st; /* Grundfos structure definition */ /****************************************************************************** * Macro Constant Declarations @@ -29,7 +34,7 @@ /****************************************************************************** * Extern Function Declarations ******************************************************************************/ -extern uint32_t GrundfosPmpFeedbackSpeed(void); -extern void GrundfosPmpEnable(uint8_t state_u8); -extern bool GrundfosPmpSetSpeed(float setSpeed_f); +uint32 GrundfosPmpFeedbackSpeed(uint8 channel_u8); +void GrundfosPmpEnable(uint8_t state_u8); +bool GrundfosPmpSetSpeed(float setSpeed_f); #endif /* GRUNDFOS_H_ */ diff --git a/EnduranceTestBench/nehemis/od_entries.h b/EnduranceTestBench/nehemis/od_entries.h index 3e2a08b..7fffee4 100644 --- a/EnduranceTestBench/nehemis/od_entries.h +++ b/EnduranceTestBench/nehemis/od_entries.h @@ -13,44 +13,49 @@ #define OD_ENTRIES_H_ /* Device Indexes */ -#define OD_ENTRY_PU_MOTOR_CTRL_INDEX 0x6000 -#define OD_ENTRY_PU_COND_DATA_IN_INDEX 0x6001 -#define OD_ENTRY_PU_COND_DATA_OUT_INDEX 0x6002 -#define OD_ENTRY_PU_MOTOR_DATA_OUT_INDEX 0x6003 -#define OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX 0x6004 -#define OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX 0x6005 +#define OD_ENTRY_PU_MOTOR_CTRL_INDEX 0x6000 +#define OD_ENTRY_PU_COND_DATA_IN_INDEX 0x6001 +#define OD_ENTRY_PU_COND_DATA_OUT_INDEX 0x6002 +#define OD_ENTRY_PU_MOTOR_DATA_OUT_INDEX 0x6003 +#define OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX 0x6004 +#define OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX 0x6005 +#define OD_ENTRY_PU_GRUNDFOS_PUMP_CONTROL_INDEX 0x6006 /* Device Sub-indexes */ -#define OD_ENTRY_PU_MOTOR_CTRL_ID_SUB_INDEX 0x01 -#define OD_ENTRY_PU_MOTOR_CTRL_CMD_SUB_INDEX 0x02 -#define OD_ENTRY_PU_MOTOR_CTRL_POS_SUB_INDEX 0x03 -#define OD_ENTRY_PU_MOTOR_CTRL_PRESSURE_SUB_INDEX 0x04 -#define OD_ENTRY_PU_MOTOR_CTRL_FLOW_SUB_INDEX 0x05 +#define OD_ENTRY_PU_MOTOR_CTRL_ID_SUB_INDEX 0x01 +#define OD_ENTRY_PU_MOTOR_CTRL_CMD_SUB_INDEX 0x02 +#define OD_ENTRY_PU_MOTOR_CTRL_POS_SUB_INDEX 0x03 +#define OD_ENTRY_PU_MOTOR_CTRL_PRESSURE_SUB_INDEX 0x04 +#define OD_ENTRY_PU_MOTOR_CTRL_FLOW_SUB_INDEX 0x05 -#define OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX 0x01 -#define OD_ENTRY_PU_COND2_DATA_IN_SUB_INDEX 0x03 -#define OD_ENTRY_PU_COND3_DATA_IN_SUB_INDEX 0x05 +#define OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX 0x01 +#define OD_ENTRY_PU_COND2_DATA_IN_SUB_INDEX 0x03 +#define OD_ENTRY_PU_COND3_DATA_IN_SUB_INDEX 0x05 -#define OD_ENTRY_PU_TEMP1_DATA_IN_SUB_INDEX 0x02 -#define OD_ENTRY_PU_TEMP2_DATA_IN_SUB_INDEX 0x04 -#define OD_ENTRY_PU_TEMP3_DATA_IN_SUB_INDEX 0x06 +#define OD_ENTRY_PU_TEMP1_DATA_IN_SUB_INDEX 0x02 +#define OD_ENTRY_PU_TEMP2_DATA_IN_SUB_INDEX 0x04 +#define OD_ENTRY_PU_TEMP3_DATA_IN_SUB_INDEX 0x06 -#define OD_ENTRY_PU_COND1_DATA_OUT_SUB_INDEX 0x01 -#define OD_ENTRY_PU_COND2_DATA_OUT_SUB_INDEX 0x03 -#define OD_ENTRY_PU_COND3_DATA_OUT_SUB_INDEX 0x05 +#define OD_ENTRY_PU_COND1_DATA_OUT_SUB_INDEX 0x01 +#define OD_ENTRY_PU_COND2_DATA_OUT_SUB_INDEX 0x03 +#define OD_ENTRY_PU_COND3_DATA_OUT_SUB_INDEX 0x05 -#define OD_ENTRY_PU_TEMP1_DATA_OUT_SUB_INDEX 0x02 -#define OD_ENTRY_PU_TEMP2_DATA_OUT_SUB_INDEX 0x04 -#define OD_ENTRY_PU_TEMP3_DATA_OUT_SUB_INDEX 0x06 +#define OD_ENTRY_PU_TEMP1_DATA_OUT_SUB_INDEX 0x02 +#define OD_ENTRY_PU_TEMP2_DATA_OUT_SUB_INDEX 0x04 +#define OD_ENTRY_PU_TEMP3_DATA_OUT_SUB_INDEX 0x06 -#define OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX 0x01 -#define OD_ENTRY_PU_FLOWMETER2_DATA_OUT_SUB_INDEX 0x02 -#define OD_ENTRY_PU_FLOWMETER3_DATA_OUT_SUB_INDEX 0x03 -#define OD_ENTRY_PU_FLOWMETER4_DATA_OUT_SUB_INDEX 0x04 +#define OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX 0x01 +#define OD_ENTRY_PU_FLOWMETER2_DATA_OUT_SUB_INDEX 0x02 +#define OD_ENTRY_PU_FLOWMETER3_DATA_OUT_SUB_INDEX 0x03 +#define OD_ENTRY_PU_FLOWMETER4_DATA_OUT_SUB_INDEX 0x04 -#define OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX 0x01 -#define OD_ENTRY_PU_PRESSURE2_DATA_OUT_SUB_INDEX 0x02 -#define OD_ENTRY_PU_PRESSURE3_DATA_OUT_SUB_INDEX 0x03 -#define OD_ENTRY_PU_PRESSURE4_DATA_OUT_SUB_INDEX 0x04 +#define OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX 0x01 +#define OD_ENTRY_PU_PRESSURE2_DATA_OUT_SUB_INDEX 0x02 +#define OD_ENTRY_PU_PRESSURE3_DATA_OUT_SUB_INDEX 0x03 +#define OD_ENTRY_PU_PRESSURE4_DATA_OUT_SUB_INDEX 0x04 + +#define OD_ENTRY_PU_GRUNDFOS_PUMP_ENABLE_SUB_INDEX 0x01 +#define OD_ENTRY_PU_GRUNDFOS_PUMP_SET_SPEED_SUB_INDEX 0x02 +#define OD_ENTRY_PU_GRUNDFOS_PUMP_FEEDBACK_SUB_INDEX 0x03 #endif /* OD_ENTRIES_H_ */ diff --git a/EnduranceTestBench/nehemis/pressureSensor.c b/EnduranceTestBench/nehemis/pressureSensor.c index 9f8ea92..1415b5e 100644 --- a/EnduranceTestBench/nehemis/pressureSensor.c +++ b/EnduranceTestBench/nehemis/pressureSensor.c @@ -13,6 +13,7 @@ * Include Header Files ******************************************************************************/ #include "pressureSensor.h" +#include "analogMeasurement.h" /****************************************************************************** * Type declarations @@ -21,27 +22,21 @@ /****************************************************************************** * Macro Constant Declarations ******************************************************************************/ -#define PRESSURE_SENSOR_ADC_REF_VOLTAGE 3.3f -#define PRESSURE_SENSOR_ADC_RESOLUTION 4095.0f /* 12-bit ADC */ /****************************************************************************** * Private function Declarations ******************************************************************************/ -static float PressureSensorReadVoltage(PressureSensorMain_st *pressureSensor_pst); +static float PressureSensorReadVoltage(uint32 channel_u32); /****************************************************************************** * Extern Function Definitions ******************************************************************************/ -void PressureSensorInit(PressureSensorMain_st *pressureSensor_pst, - ADC_HandleTypeDef *adcHandle_pst, uint32_t channel_u32) +void PressureSensorInit(PressureSensorMain_st *pressureSensor_pst) { - if (pressureSensor_pst == NULL || adcHandle_pst == NULL) + if (pressureSensor_pst == NULL) { /* ERROR */ } - - pressureSensor_pst->adcHandle_pst = adcHandle_pst; - pressureSensor_pst->channel_u32 = channel_u32; } @@ -52,7 +47,7 @@ void PressureSensorGetVal(PressureSensorMain_st *pressureSensor_pst) /* ERROR */ } - pressureSensor_pst->rawT_f32 = (PressureSensorReadVoltage(pressureSensor_pst) - 0.5f) / 0.2f; + pressureSensor_pst->rawT_f32 = (PressureSensorReadVoltage(pressureSensor_pst->channel_u32) - 0.5f) / 0.2f; } @@ -67,40 +62,12 @@ void PressureSensorGetVal(PressureSensorMain_st *pressureSensor_pst) * @return ADC output voltage based on sensor reading. * */ -static float32 PressureSensorReadVoltage(PressureSensorMain_st *pressureSensor_pst) +static float32 PressureSensorReadVoltage(uint32 channel_u32) { - uint32 adcVal_u32 = 0uL; - if (pressureSensor_pst == NULL || pressureSensor_pst->adcHandle_pst == NULL) - { - return 0.0f; /* Error Case */ - } - - ADC_ChannelConfTypeDef sConfig = {0}; - sConfig.Channel = pressureSensor_pst->channel_u32; /* Set the channel specific to this flowmeter */ - sConfig.Rank = ADC_REGULAR_RANK_1; - sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5; - - if (HAL_ADC_ConfigChannel(pressureSensor_pst->adcHandle_pst, &sConfig) != HAL_OK) - { - return 0.0f; /* ERROR */ - } - - /* Start ADC conversion and poll for completion */ - if (HAL_ADC_Start(pressureSensor_pst->adcHandle_pst) == HAL_OK) - { - if (HAL_ADC_PollForConversion(pressureSensor_pst->adcHandle_pst, HAL_MAX_DELAY) == HAL_OK) - { - adcVal_u32 = HAL_ADC_GetValue(pressureSensor_pst->adcHandle_pst); - } - HAL_ADC_Stop(pressureSensor_pst->adcHandle_pst); - } - else - { - /* ERROR */ - } - /* Convert ADC value to voltage (assuming 12-bit resolution and 3.3V reference) */ - float32 voltage_f32 = (float32)adcVal_u32 * (PRESSURE_SENSOR_ADC_REF_VOLTAGE / PRESSURE_SENSOR_ADC_RESOLUTION); + uint32 adcVal_u32 = 0uL; + AnalogMeasurementReadData(channel_u32, &adcVal_u32); + float32 voltage_f32 = (float32)adcVal_u32 * (ANALOG_MEAS_ADC_REF_VOLTAGE / ANALOG_MEAS_ADC_RESOLUTION); return voltage_f32; } diff --git a/EnduranceTestBench/nehemis/pressureSensor.h b/EnduranceTestBench/nehemis/pressureSensor.h index 3907271..7148bb8 100644 --- a/EnduranceTestBench/nehemis/pressureSensor.h +++ b/EnduranceTestBench/nehemis/pressureSensor.h @@ -19,7 +19,6 @@ ******************************************************************************/ typedef struct { - ADC_HandleTypeDef *adcHandle_pst; uint32 channel_u32; float32 rawT_f32; } PressureSensorMain_st; /* HubaPressure sensor structure definition */ @@ -27,10 +26,7 @@ typedef struct /****************************************************************************** * Macro Constant Declarations ******************************************************************************/ -#define PRESSURE_SENSOR_PS1_ADC_CHANNEL 1u -#define PRESSURE_SENSOR_PS2_ADC_CHANNEL 2u -#define PRESSURE_SENSOR_PS3_ADC_CHANNEL 3u -#define PRESSURE_SENSOR_PS4_ADC_CHANNEL 4u + /****************************************************************************** * Extern Function Declarations ******************************************************************************/ @@ -38,14 +34,11 @@ typedef struct * @brief Init function of the Pressure sensor module. * * @param pressureSensor_pst : Pointer to main strucutre of the module. - * adcHandle_pst : ADC handler f the flowmeter. - * channel_u32 : ADC channel of the connected sensor to use. * * @return Pressure value. * */ -void PressureSensorInit(PressureSensorMain_st *pressureSensor_pst, - ADC_HandleTypeDef *adcHandle_pst, uint32 channel_u32); +void PressureSensorInit(PressureSensorMain_st *pressureSensor_pst); /** * @brief Function to get pressure value. diff --git a/EnduranceTestBench/nehemis/processBoard.c b/EnduranceTestBench/nehemis/processBoard.c index 3696d5b..278ceaa 100644 --- a/EnduranceTestBench/nehemis/processBoard.c +++ b/EnduranceTestBench/nehemis/processBoard.c @@ -15,8 +15,10 @@ #include "processBoard.h" #include "flowmeter.h" #include "pressureSensor.h" +#include "grundfos.h" #include "od_entries.h" -#include "co_odaccess.h" +#include "nms_can.h" +#include "analogMeasurement.h" /****************************************************************************** * Type declarations ******************************************************************************/ @@ -24,14 +26,14 @@ /****************************************************************************** * Macro Constant Declarations ******************************************************************************/ -#define PROCESS_BOARD_VALVE_POS_INDEX 0x6002 -#define PROCESS_BOARD_VALVE_FLOW_INDEX 0x6006 -#define PROCESS_BOARD_VALVE_PRESSURE_INDEX 0x6001 +#define PROCESS_BOARD_VALVE_POS_INDEX 0x6002 +#define PROCESS_BOARD_VALVE_FLOW_INDEX 0x6006 +#define PROCESS_BOARD_VALVE_PRESSURE_INDEX 0x6001 -#define PROCESS_BOARD_VALVE_SUB_INDEX 0x0 +#define PROCESS_BOARD_VALVE_SUB_INDEX 0x0 -#define PROCESS_BOARD_FLOWMETER_ADC_MODULE &hadc1 -#define PROCESS_BOARD_PRESSURE_SENSOR_ADC_MODULE &hadc1 +#define PU_CANOPEN_SLAVE_LINE 0u +#define PU_CANOPEN_MASTER_LINE 1u /****************************************************************************** * Global variables ******************************************************************************/ @@ -49,6 +51,8 @@ PressureSensorMain_st pressureSensorPS2_gst; PressureSensorMain_st pressureSensorPS3_gst; PressureSensorMain_st pressureSensorPS4_gst; +GrundfosMain_st grundfosPMP_gst; + ProcessBoardCondDataSt condBoard1_gst; ProcessBoardCondDataSt condBoard2_gst; ProcessBoardCondDataSt condBoard3_gst; @@ -70,9 +74,10 @@ static void ProcessBoardTriggerMvCartCtrl(uint8 motorId_u8, uint8 flowRate_u8, u static void ProcessBoardReadCondDataIN(void); static void ProcessBoardWriteCondDataOUT(void); static void ProcessBoardReadMvDataIN(void); -static void ProcessBoardFlowmeterDataOUT(FlowmeterMain_st flowmeter_st); -static void ProcessBoardPressureSensorDataOUT(PressureSensorMain_st pressureSensor_st); - +static void ProcessBoardFlowmeterDataOUT(float32 rawQ_f32); +static void ProcessBoardPressureSensorDataOUT(float32 rawT_f32); +static void ProcessBoardPumpSpeedDataOUT(uint32 pmpSpeed_u32); +static void ProcessBoardGrundfosPumpHandler(void); /****************************************************************************** * Extern Function Declarations ******************************************************************************/ @@ -80,48 +85,73 @@ void ProcessBoardInit(void) { motorCmd_gu8 = 0u; - FlowmeterInit(&flowmeterFM1_gst, PROCESS_BOARD_FLOWMETER_ADC_MODULE, FLOWMETER_FM1_ADC_CHANNEL); - PressureSensorInit(&pressureSensorPS1_gst, PROCESS_BOARD_PRESSURE_SENSOR_ADC_MODULE, PRESSURE_SENSOR_PS1_ADC_CHANNEL); + /* Initializing the structures (Pressure sensor, Flow + * meter, and Grundfos) with their respective ADC channel */ + pressureSensorPS1_gst.channel_u32 = PS1_ADC_CHANNEL; + pressureSensorPS2_gst.channel_u32 = PS2_ADC_CHANNEL; + pressureSensorPS3_gst.channel_u32 = PS3_ADC_CHANNEL; + pressureSensorPS4_gst.channel_u32 = PS4_ADC_CHANNEL; - FlowmeterInit(&flowmeterFM2_gst, PROCESS_BOARD_FLOWMETER_ADC_MODULE, FLOWMETER_FM2_ADC_CHANNEL); - PressureSensorInit(&pressureSensorPS2_gst, PROCESS_BOARD_PRESSURE_SENSOR_ADC_MODULE, PRESSURE_SENSOR_PS2_ADC_CHANNEL); + grundfosPMP_gst.channel_u32 = PMP_ADC_CHANNEL; - FlowmeterInit(&flowmeterFM3_gst, PROCESS_BOARD_FLOWMETER_ADC_MODULE, FLOWMETER_FM3_ADC_CHANNEL); - PressureSensorInit(&pressureSensorPS3_gst, PROCESS_BOARD_PRESSURE_SENSOR_ADC_MODULE, PRESSURE_SENSOR_PS3_ADC_CHANNEL); - - FlowmeterInit(&flowmeterFM4_gst, PROCESS_BOARD_FLOWMETER_ADC_MODULE, FLOWMETER_FM4_ADC_CHANNEL); - PressureSensorInit(&pressureSensorPS4_gst, PROCESS_BOARD_PRESSURE_SENSOR_ADC_MODULE, PRESSURE_SENSOR_PS4_ADC_CHANNEL); + flowmeterFM1_gst.channel_u32 = FM1_ADC_CHANNEL; + flowmeterFM2_gst.channel_u32 = FM2_ADC_CHANNEL; + flowmeterFM3_gst.channel_u32 = FM3_ADC_CHANNEL; + flowmeterFM4_gst.channel_u32 = FM4_ADC_CHANNEL; + FlowmeterInit(&flowmeterFM1_gst); + FlowmeterInit(&flowmeterFM2_gst); + FlowmeterInit(&flowmeterFM3_gst); + FlowmeterInit(&flowmeterFM4_gst); } void ProcessBoardRun(void) { - uint8 id_u8; - uint8 motorCmd_u8; - uint8 posData_u8; - uint8 flowRate_u8; - uint8 pressure_u8; - - coOdGetObj_u8(OD_ENTRY_PU_MOTOR_CTRL_INDEX, OD_ENTRY_PU_MOTOR_CTRL_ID_SUB_INDEX, &id_u8); - coOdGetObj_u8(OD_ENTRY_PU_MOTOR_CTRL_INDEX, OD_ENTRY_PU_MOTOR_CTRL_CMD_SUB_INDEX, &motorCmd_u8); - coOdGetObj_u8(OD_ENTRY_PU_MOTOR_CTRL_INDEX, OD_ENTRY_PU_MOTOR_CTRL_POS_SUB_INDEX, &posData_u8); - coOdGetObj_u8(OD_ENTRY_PU_MOTOR_CTRL_INDEX, OD_ENTRY_PU_MOTOR_CTRL_PRESSURE_SUB_INDEX, &flowRate_u8); - coOdGetObj_u8(OD_ENTRY_PU_MOTOR_CTRL_INDEX, OD_ENTRY_PU_MOTOR_CTRL_FLOW_SUB_INDEX, &pressure_u8); + uint8 id_u8 = 0u; + uint8 motorCmd_u8 = 0u; + uint8 posData_u8 = 0u; + uint8 flowRate_u8 = 0u; + uint8 pressure_u8 = 0u; + AnalogMesaurementRun(); + /* DEBUG code to be replaced. Logic to be changed based on state machine + * implementation. */ if(motorCmd_u8 == 1u) { - ProcessBoardTriggerMvPosCtrl(11, posData_u8); + ProcessBoardTriggerMvPosCtrl(11, posData_u8); /* DEBUG */ } else { ProcessBoardTriggerMvCartCtrl(id_u8, flowRate_u8, pressure_u8); } + /* Flowmeter data IN */ + FlowmeterGetFlow(&flowmeterFM1_gst); + FlowmeterGetFlow(&flowmeterFM2_gst); + FlowmeterGetFlow(&flowmeterFM3_gst); FlowmeterGetFlow(&flowmeterFM4_gst); + + /* Pressure sensor data IN */ PressureSensorGetVal(&pressureSensorPS1_gst); - ProcessBoardFlowmeterDataOUT(flowmeterFM4_gst); - ProcessBoardPressureSensorDataOUT(pressureSensorPS1_gst); + PressureSensorGetVal(&pressureSensorPS2_gst); + PressureSensorGetVal(&pressureSensorPS3_gst); + PressureSensorGetVal(&pressureSensorPS4_gst); + + /* Flowmeter data OUT */ + ProcessBoardFlowmeterDataOUT(flowmeterFM1_gst.rawQ_f32); + ProcessBoardFlowmeterDataOUT(flowmeterFM2_gst.rawQ_f32); + ProcessBoardFlowmeterDataOUT(flowmeterFM3_gst.rawQ_f32); + ProcessBoardFlowmeterDataOUT(flowmeterFM4_gst.rawQ_f32); + + /* Pressure sensor data OUT */ + ProcessBoardPressureSensorDataOUT(pressureSensorPS1_gst.rawT_f32); + ProcessBoardPressureSensorDataOUT(pressureSensorPS2_gst.rawT_f32); + ProcessBoardPressureSensorDataOUT(pressureSensorPS3_gst.rawT_f32); + ProcessBoardPressureSensorDataOUT(pressureSensorPS4_gst.rawT_f32); + + ProcessBoardGrundfosPumpHandler(); + ProcessBoardReadCondDataIN(); ProcessBoardWriteCondDataOUT(); } @@ -130,6 +160,88 @@ void ProcessBoardRun(void) /****************************************************************************** * Private function definitions ******************************************************************************/ +//static void ProcessBoardGrundfosPumpHandler(void) +//{ +// uint32 pmpSpeed_u32 = 0uL; +// uint8 mode_u8 = 0u; +// uint8 speed_u8 = 0u; +// +// NmsCanGetObj_u8(OD_ENTRY_PU_GRUNDFOS_PUMP_CONTROL_INDEX, OD_ENTRY_PU_GRUNDFOS_PUMP_ENABLE_SUB_INDEX, &mode_u8); +// NmsCanGetObj_u8(OD_ENTRY_PU_GRUNDFOS_PUMP_CONTROL_INDEX, OD_ENTRY_PU_GRUNDFOS_PUMP_SET_SPEED_SUB_INDEX, &speed_u8); +// +// GrundfosPmpEnable(mode_u8); +// if(mode_u8 == 1u) +// { +// GrundfosPmpSetSpeed(speed_u8); +// /* Grundfos Pump feedback speed OUT */ +// pmpSpeed_u32 = GrundfosPmpFeedbackSpeed(PMP_ADC_CHANNEL); +// } +// else +// { +// pmpSpeed_u32 = 0uL; +// } +// ProcessBoardPumpSpeedDataOUT(pmpSpeed_u32); +//} + +static void ProcessBoardGrundfosPumpHandler(void) +{ + uint32 pmpSpeed_u32 = 0uL; + uint8 mode_u8 = 0u; + static uint8 speed_u8 = 0u; + static uint32 elapsedTime_s = 0u; + static enum { INCREASING, DECREASING } speedState = INCREASING; + + NmsCanGetObj_u8(OD_ENTRY_PU_GRUNDFOS_PUMP_CONTROL_INDEX, OD_ENTRY_PU_GRUNDFOS_PUMP_ENABLE_SUB_INDEX, &mode_u8); + + // Only modify speed every 15 minutes (900 seconds) + if (elapsedTime_s >= 900) + { + elapsedTime_s = 0; // Reset time counter + + if (speedState == INCREASING) + { + if (speed_u8 < 10) + { + speed_u8 += 2; + } + if (speed_u8 >= 10) + { + speedState = DECREASING; // Switch to decreasing mode + } + } + else // DECREASING + { + if (speed_u8 > 0) + { + speed_u8 -= 2; + } + if (speed_u8 == 0) + { + speedState = INCREASING; // Switch back to increasing mode + } + } + } + else + { + elapsedTime_s++; // Increment elapsed time + } + + GrundfosPmpEnable(mode_u8); + if (mode_u8 == 1u) + { + GrundfosPmpSetSpeed(speed_u8); + /* Grundfos Pump feedback speed OUT */ + pmpSpeed_u32 = GrundfosPmpFeedbackSpeed(PMP_ADC_CHANNEL); + } + else + { + pmpSpeed_u32 = 0uL; + } + ProcessBoardPumpSpeedDataOUT(pmpSpeed_u32); +} + + + static void ProcessBoardTriggerMvPosCtrl(uint8 motorId_u8, uint8 posData_u8) { @@ -144,49 +256,55 @@ static void ProcessBoardTriggerMvCartCtrl(uint8 motorId_u8, uint8 flowRate_u8, u static void ProcessBoardReadCondDataIN(void) { - coOdGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, &condBoard1_gst.conductivityData_u32); - coOdGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_TEMP1_DATA_IN_SUB_INDEX, &condBoard1_gst.temperature_u32); + NmsCanGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, &condBoard1_gst.conductivityData_u32); + NmsCanGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_TEMP1_DATA_IN_SUB_INDEX, &condBoard1_gst.temperature_u32); - coOdGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, &condBoard2_gst.conductivityData_u32); - coOdGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_TEMP2_DATA_IN_SUB_INDEX, &condBoard2_gst.temperature_u32); + NmsCanGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, &condBoard2_gst.conductivityData_u32); + NmsCanGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_TEMP2_DATA_IN_SUB_INDEX, &condBoard2_gst.temperature_u32); - coOdGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, &condBoard3_gst.conductivityData_u32); - coOdGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_TEMP3_DATA_IN_SUB_INDEX, &condBoard3_gst.temperature_u32); + NmsCanGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, &condBoard3_gst.conductivityData_u32); + NmsCanGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_TEMP3_DATA_IN_SUB_INDEX, &condBoard3_gst.temperature_u32); } static void ProcessBoardWriteCondDataOUT(void) { - coOdPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, condBoard1_gst.conductivityData_u32); - coOdPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_TEMP1_DATA_IN_SUB_INDEX, condBoard1_gst.temperature_u32); + NmsCanPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, condBoard1_gst.conductivityData_u32); + NmsCanPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_TEMP1_DATA_IN_SUB_INDEX, condBoard1_gst.temperature_u32); - coOdPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_COND2_DATA_IN_SUB_INDEX, condBoard2_gst.conductivityData_u32); - coOdPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_TEMP2_DATA_IN_SUB_INDEX, condBoard2_gst.temperature_u32); + NmsCanPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_COND2_DATA_IN_SUB_INDEX, condBoard2_gst.conductivityData_u32); + NmsCanPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_TEMP2_DATA_IN_SUB_INDEX, condBoard2_gst.temperature_u32); - coOdPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_COND3_DATA_IN_SUB_INDEX, condBoard3_gst.conductivityData_u32); - coOdPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_TEMP3_DATA_IN_SUB_INDEX, condBoard3_gst.temperature_u32); + NmsCanPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_COND3_DATA_IN_SUB_INDEX, condBoard3_gst.conductivityData_u32); + NmsCanPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_TEMP3_DATA_IN_SUB_INDEX, condBoard3_gst.temperature_u32); } -static void ProcessBoardFlowmeterDataOUT(FlowmeterMain_st flowmeter_st) +static void ProcessBoardFlowmeterDataOUT(float32 rawQ_f32) { - coOdPutObj_r32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, flowmeterFM1_gst.rawQ_f32); - coOdPutObj_r32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, flowmeterFM2_gst.rawQ_f32); - coOdPutObj_r32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, flowmeterFM3_gst.rawQ_f32); - coOdPutObj_r32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, flowmeterFM4_gst.rawQ_f32); + NmsCanPutObj_f32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, rawQ_f32); + NmsCanPutObj_f32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, rawQ_f32); + NmsCanPutObj_f32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, rawQ_f32); + NmsCanPutObj_f32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, rawQ_f32); } -static void ProcessBoardPressureSensorDataOUT(PressureSensorMain_st pressureSensor_st) +static void ProcessBoardPressureSensorDataOUT(float32 rawT_f32) { - coOdPutObj_r32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, pressureSensorPS1_gst.rawT_f32); - coOdPutObj_r32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, pressureSensorPS2_gst.rawT_f32); - coOdPutObj_r32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, pressureSensorPS3_gst.rawT_f32); - coOdPutObj_r32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, pressureSensorPS4_gst.rawT_f32); + NmsCanPutObj_f32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, rawT_f32); + NmsCanPutObj_f32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, rawT_f32); + NmsCanPutObj_f32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, rawT_f32); + NmsCanPutObj_f32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, rawT_f32); +} + + +static void ProcessBoardPumpSpeedDataOUT(uint32 pmpSpeed_u32) +{ + NmsCanPutObj_u32(OD_ENTRY_PU_GRUNDFOS_PUMP_CONTROL_INDEX, OD_ENTRY_PU_GRUNDFOS_PUMP_FEEDBACK_SUB_INDEX, pmpSpeed_u32); } static void ProcessBoardReadMvDataIN(void) { - /* To be implemented */ +// NmsCanGetObj_u8(uint8 canLine_u8, uint16 index_u16, uint8 subIndex_u8, uint8 *pObj_pu8); } diff --git a/EnduranceTestBench/nehemis/test.c b/EnduranceTestBench/nehemis/test.c new file mode 100644 index 0000000..11b79f8 --- /dev/null +++ b/EnduranceTestBench/nehemis/test.c @@ -0,0 +1,298 @@ +/** + * @file batch_endurance_testbench.c + * + * @brief Batch mode test bench: + * 1. Write to all nodes (at 100ms intervals) + * 2. Read all nodes + * 3. Verify positions (retry mismatch up to 2 times) + * 4. Cycle complete – reset for next iteration + * + * @copyright + */ + +#include "enduranceTestBench.h" +#include "stdlib.h" + +/* CANopen includes */ +#include +#include +#include "../nms_hal/hal_system.h" + +/****************************************************************************** + * Macro constant declarations + ******************************************************************************/ +#define ENDURANCE_TEST_BENCH_MAX_RETRY_CNT 3u +#define ENDURANCE_TEST_BENCH_TIMEOUT 1000u +#define ENDURANCE_TEST_BENCH_LSS_NODE_COUNT 20u +#define ENDURANCE_TEST_BENCH_POSITION_SETPOINT_INDEX 0x6002 +#define ENDURANCE_TEST_BENCH_POSITION_SETPOINT_SUB_INDEX 0x0 +#define ENDURANCE_TEST_BENCH_POSITION_FEEDBACK_INDEX 0x6004 +#define ENDURANCE_TEST_BENCH_POSITION_FEEDBACK_SUB_INDEX 0x0 + +/* Batch delay between node operations (in ms) */ +#define NODE_OP_DELAY_MS 100u + +/****************************************************************************** + * Type Declarations + ******************************************************************************/ +typedef enum +{ + TEST_BENCH_BATCH_WRITE, /* Write to nodes in batch */ + TEST_BENCH_BATCH_WRITE_WAIT, /* Wait between writes */ + TEST_BENCH_BATCH_READ, /* Read all nodes */ + TEST_BENCH_BATCH_READ_WAIT, /* Wait between reads */ + TEST_BENCH_BATCH_VERIFY, /* Verify all nodes */ + TEST_BENCH_CYCLE_COMPLETE, /* End of cycle, reset for next iteration */ + TEST_BENCH_IDLE /* Idle state (optional) */ +} SdlTestBenchState_en; + +typedef enum +{ + TEST_BENCH_DATA_VERIF_DEFAULT, + TEST_BENCH_DATA_VERIF_SUCCESS, + TEST_BENCH_DATA_VERIF_FAILURE, + TEST_BENCH_DATA_VERIF_SKIPPED, +} TestBenchStatus_en; + +typedef struct +{ + uint8 targetPositions_gau8[ENDURANCE_TEST_BENCH_LSS_NODE_COUNT]; + uint8 readPosition_gau8[ENDURANCE_TEST_BENCH_LSS_NODE_COUNT]; + TestBenchStatus_en status_en[ENDURANCE_TEST_BENCH_LSS_NODE_COUNT]; +} TestBenchData_en; + +/****************************************************************************** + * Global variable declarations + ******************************************************************************/ +static TestBenchData_en testBenchData_en; +static uint8 currentNode_gu8 = 0u; +static SdlTestBenchState_en testBenchState_en = TEST_BENCH_IDLE; +static uint32 readPosition_gu32; +static uint8 storedTargetPos = 0u; /* Flag: target written to current node */ +static uint8 readMismatchRetries_u8 = 0u; /* Retry count for verify mismatches */ + +static uint64 writeTime_u64 = 0uLL; +static uint64 readExecutedTime_u64 = 0uLL; +static uint64 cycleStartTime_u64 = 0uLL; +static uint8 retries_u8 = 0u; /* General retry counter for SDO communication */ + +/****************************************************************************** + * Public Function Definitions + ******************************************************************************/ +void TestRun(void) +{ + uint64 currentTime_u64; + HalSystemGetRunTimeMs(¤tTime_u64); + + /* Initialization: start new cycle if in idle or cycle complete state */ + if (testBenchState_en == TEST_BENCH_IDLE || testBenchState_en == TEST_BENCH_CYCLE_COMPLETE) + { + /* Prepare new cycle: reset all node statuses and choose new target positions */ + for (uint8 i = 0u; i < ENDURANCE_TEST_BENCH_LSS_NODE_COUNT; i++) + { + testBenchData_en.targetPositions_gau8[i] = (uint8)(rand() % 256); + testBenchData_en.readPosition_gau8[i] = 0u; + testBenchData_en.status_en[i] = TEST_BENCH_DATA_VERIF_DEFAULT; + } + currentNode_gu8 = 0u; + storedTargetPos = 0u; + retries_u8 = 0u; + readMismatchRetries_u8 = 0u; + cycleStartTime_u64 = currentTime_u64; + testBenchState_en = TEST_BENCH_BATCH_WRITE; + } + + switch (testBenchState_en) + { + /* -------------------- Batch Write -------------------- */ + case TEST_BENCH_BATCH_WRITE: + { + if (currentNode_gu8 < ENDURANCE_TEST_BENCH_LSS_NODE_COUNT) + { + if (storedTargetPos == 0) + { + /* Use the pre-assigned target value for this node */ + uint8 value_u8 = testBenchData_en.targetPositions_gau8[currentNode_gu8]; + + RET_T retVal_en = coSdoWrite( + (currentNode_gu8 + 1), + ENDURANCE_TEST_BENCH_POSITION_SETPOINT_INDEX, + ENDURANCE_TEST_BENCH_POSITION_SETPOINT_SUB_INDEX, + &value_u8, + sizeof(uint8), + CO_FALSE, + ENDURANCE_TEST_BENCH_TIMEOUT + ); + + if (retVal_en == RET_OK) + { + storedTargetPos = 1; /* Mark that target is written for this node */ + HalSystemGetRunTimeMs(&writeTime_u64); + retries_u8 = 0u; + testBenchState_en = TEST_BENCH_BATCH_WRITE_WAIT; + } + else + { + retries_u8++; + if (retries_u8 >= ENDURANCE_TEST_BENCH_MAX_RETRY_CNT) + { + testBenchData_en.status_en[currentNode_gu8] = TEST_BENCH_DATA_VERIF_SKIPPED; + /* Mark node as skipped and move on */ + currentNode_gu8++; + retries_u8 = 0u; + storedTargetPos = 0u; + testBenchState_en = TEST_BENCH_BATCH_WRITE; + } + } + } + } + else + { + /* Finished writing to all nodes */ + currentNode_gu8 = 0u; /* Reset index for read phase */ + testBenchState_en = TEST_BENCH_BATCH_READ; + } + break; + } + + case TEST_BENCH_BATCH_WRITE_WAIT: + { + /* Wait 100ms between writes */ + if ((currentTime_u64 - writeTime_u64) >= 500) + { + /* Move to next node write */ + currentNode_gu8++; + storedTargetPos = 0u; /* Reset for next node */ + testBenchState_en = TEST_BENCH_BATCH_WRITE; + } + break; + } + + /* -------------------- Batch Read -------------------- */ + case TEST_BENCH_BATCH_READ: + { + if (currentNode_gu8 < ENDURANCE_TEST_BENCH_LSS_NODE_COUNT) + { + RET_T retVal_en = coSdoRead( + (currentNode_gu8 + 1), + ENDURANCE_TEST_BENCH_POSITION_FEEDBACK_INDEX, + ENDURANCE_TEST_BENCH_POSITION_FEEDBACK_SUB_INDEX, + (uint8*)&readPosition_gu32, + sizeof(uint32), + CO_FALSE, + ENDURANCE_TEST_BENCH_TIMEOUT + ); + + if (retVal_en == RET_OK) + { + retries_u8 = 0u; + /* The read indication callback is assumed to update + * testBenchData_en.readPosition_gau8[currentNode_gu8] and + * then we simply continue to next node after a small delay. + */ + HalSystemGetRunTimeMs(&readExecutedTime_u64); + testBenchData_en.readPosition_gau8[currentNode_gu8] = (uint8)readPosition_gu32; + testBenchState_en = TEST_BENCH_BATCH_READ_WAIT; + } + else if (retVal_en == RET_SERVICE_BUSY && retries_u8 < ENDURANCE_TEST_BENCH_MAX_RETRY_CNT) + { + retries_u8++; + } + else + { + /* If read fails, mark as skipped and move on */ + testBenchData_en.status_en[currentNode_gu8] = TEST_BENCH_DATA_VERIF_SKIPPED; + currentNode_gu8++; + retries_u8 = 0u; + } + } + else + { + /* Finished reading all nodes */ + currentNode_gu8 = 0u; /* Reset for verification phase */ + testBenchState_en = TEST_BENCH_BATCH_VERIFY; + } + break; + } + + case TEST_BENCH_BATCH_READ_WAIT: + { + /* Wait 100ms between node reads */ + if ((currentTime_u64 - readExecutedTime_u64) >= 10) + { + currentNode_gu8++; + testBenchState_en = TEST_BENCH_BATCH_READ; + } + break; + } + + /* -------------------- Batch Verify -------------------- */ + case TEST_BENCH_BATCH_VERIFY: + { + if (currentNode_gu8 < ENDURANCE_TEST_BENCH_LSS_NODE_COUNT) + { + /* Process only if the node was not already skipped */ + if (testBenchData_en.status_en[currentNode_gu8] != TEST_BENCH_DATA_VERIF_SKIPPED) + { + uint8 diff = abs(testBenchData_en.targetPositions_gau8[currentNode_gu8] - + testBenchData_en.readPosition_gau8[currentNode_gu8]); + + if (diff <= 1) + { + testBenchData_en.status_en[currentNode_gu8] = TEST_BENCH_DATA_VERIF_SUCCESS; + } + else + { + testBenchData_en.status_en[currentNode_gu8] = TEST_BENCH_DATA_VERIF_FAILURE; + } + } + /* Move to the next node in any case */ + currentNode_gu8++; + testBenchState_en = TEST_BENCH_BATCH_VERIFY; + } + else + { + /* All nodes verified; complete cycle */ + testBenchState_en = TEST_BENCH_CYCLE_COMPLETE; + } + break; + } + + /* -------------------- Cycle Complete -------------------- */ + case TEST_BENCH_CYCLE_COMPLETE: + { + /* Optionally, you can log or process the batch results here */ + /* Reset all node data for the next cycle */ + for (uint8 i = 0u; i < ENDURANCE_TEST_BENCH_LSS_NODE_COUNT; i++) + { + testBenchData_en.targetPositions_gau8[i] = 0u; + testBenchData_en.readPosition_gau8[i] = 0u; + testBenchData_en.status_en[i] = TEST_BENCH_DATA_VERIF_DEFAULT; + } + currentNode_gu8 = 0u; + storedTargetPos = 0u; + retries_u8 = 0u; + readMismatchRetries_u8 = 0u; + /* Start next cycle */ + testBenchState_en = TEST_BENCH_IDLE; + break; + } + + default: + break; + } +} + +/****************************************************************************** + * Callback Functions + ******************************************************************************/ +void TestReadInd(uint8 sdoNr_u8, uint16 index_u16, uint8 subIndex_u8, uint32 errorVal_u32) +{ + HalSystemGetRunTimeMs(&writeTime_u64); +} + +void TestWriteInd(uint8 sdoNr_u8, uint16 index_u16, uint8 subIndex_u8, uint32 size, uint32 errorVal_u32) +{ + HalSystemGetRunTimeMs(&readExecutedTime_u64); + //testBenchData_en.readPosition_gau8[currentNode_gu8] = (uint8)readPosition_gu32; +} diff --git a/EnduranceTestBench/nehemis/test.h b/EnduranceTestBench/nehemis/test.h new file mode 100644 index 0000000..03acdcc --- /dev/null +++ b/EnduranceTestBench/nehemis/test.h @@ -0,0 +1,32 @@ +/** + * @file test.h + * + * @copyright Nehemis SARL reserves all rights even in the event of industrial + * property rights. We reserve all rights of disposal such as + * copying and passing on to third parties. + * + * @brief + * + */ +#ifndef TEST_H_ +#define TEST_H_ + +/****************************************************************************** + * Include Header Files + ******************************************************************************/ + +/****************************************************************************** + * Type declarations + ******************************************************************************/ + +/****************************************************************************** + * Extern Function Declarations + ******************************************************************************/ +void TestRun(void); + +void TestInit(void); + +void TestWriteInd(uint8 sdoNr, UNSIGNED16 index, uint8 subIndex, UNSIGNED32 errorVal); + +void TestReadInd(uint8 sdoNr, UNSIGNED16 index, uint8 subIndex, UNSIGNED32 size, UNSIGNED32 errorVal); +#endif /* TEST_H_ */ diff --git a/EnduranceTestBench/nms-hal/hal_system.c b/EnduranceTestBench/nms-hal/hal_system.c deleted file mode 100644 index b69b1af..0000000 --- a/EnduranceTestBench/nms-hal/hal_system.c +++ /dev/null @@ -1,249 +0,0 @@ -/** - * @file hal_system.c - * @copyright Nehemis SARL reserves all rights even in the event of industrial - * property rights. We reserve all rights of disposal such as - * copying and passing on to third parties. - * - * - * @brief HAL layer for the SYSTEM module. - * - The system reset cause such as : - * 1. Software reset - * 2. Watchdog reset - * 3. Power on reset - * 4. Optional byte load reset - * 5. Low power reset - * 6. Pin reset - * - The NVIC enable/disable interrupts. - * - The serial number of the MCU. - */ - -/****************************************************************************** - * Include Header Files - ******************************************************************************/ -#include "hal_system.h" - -/* cubeMX */ -#include "main.h" -/****************************************************************************** - * Macro Constant Declarations - ******************************************************************************/ -#define HAL_SYSTEM_STACK_GUARD 0xCDu - -/****************************************************************************** - * Module Global Variable Declarations - ******************************************************************************/ -static uint64 systemStepCounter_gu64; -static uint64 systemPeriodMsToUs_gu64; -static uint64 systemTickLoadValue_gu64; -static uint32 resetStatusRegister_gu32; - -/****************************************************************************** - * Static Function Declarations - ******************************************************************************/ - -/****************************************************************************** - * Extern Function Definitions - ******************************************************************************/ -uint32 HalSystemInit(void) -{ - uint32 error_u32 = NMS_ERR_NONE; - - resetStatusRegister_gu32 = RCC->CSR; - RCC->CSR |= RCC_CSR_RMVF; /* RMVF = ReMoVe Flag. Reset the reset cause register for the next reboot. */ - - systemPeriodMsToUs_gu64 = HAL_GetTickFreq() * 1000uLL; - systemTickLoadValue_gu64 = (uint64)(SysTick->LOAD); - systemStepCounter_gu64 = 0uLL; - - return error_u32; -} - - -uint32 HalSystemGetRunTimeUs(uint64 * resultUs_pu64) -{ - static uint64 previousTimeUs_u64 = 0uLL; - uint32 error_u32 = NMS_ERR_NONE; - uint64 timeUs_u64 = 0uLL; - - /* Make a copy in case of multiple function instance at the same time */ - uint64 copySystemStepCounter_u64 = systemStepCounter_gu64; - - /* First make a copy of the systemStepCounter to be able to check rollback further on. - * Also copy current value of the System Tick Timer to avoid any dynamic update during calculation. - * Then translate in microsecond & sum both timing information (step counter + tick value) to get the most - * accurate resolution of the system runtime. - */ - uint64 copyPreviousTimeUs_u64 = previousTimeUs_u64; - uint64 tickValue_u64 = (uint64)(SysTick->VAL); - timeUs_u64 = copySystemStepCounter_u64 * systemPeriodMsToUs_gu64; - timeUs_u64 += ((systemTickLoadValue_gu64 - tickValue_u64) * systemPeriodMsToUs_gu64) / systemTickLoadValue_gu64; - - /* We check here if the interruption of the systick happened during our operations and correct it accordingly */ - if(timeUs_u64 <= (uint64)(systemStepCounter_gu64 * systemPeriodMsToUs_gu64)) - { - copySystemStepCounter_u64 = systemStepCounter_gu64; - tickValue_u64 = (uint64)(SysTick->VAL); - timeUs_u64 = copySystemStepCounter_u64 * systemPeriodMsToUs_gu64; - timeUs_u64 += ((systemTickLoadValue_gu64 - tickValue_u64) * systemPeriodMsToUs_gu64) / systemTickLoadValue_gu64; - - /* The timer interruption is too fast, no time to process */ - if(timeUs_u64 <= (uint64)(systemStepCounter_gu64 * systemPeriodMsToUs_gu64)) - { - error_u32 = NMS_ERR_OVERRUN; - } - } - - /* Should never happen if this timer interruption is set to highest priority */ - if(copyPreviousTimeUs_u64 > timeUs_u64) - { - error_u32 = NMS_ERR_UNKNOWN; - } - else - { - *resultUs_pu64 = previousTimeUs_u64; - } - - /* This condition has been added to prevent trouble overflow with interruptions - on the medium and high optimizations options */ - *resultUs_pu64 = (timeUs_u64 > previousTimeUs_u64) ? timeUs_u64 : *resultUs_pu64; - - return error_u32; -} - - -/* This function should not call the log, since it uses the system runtime. */ -uint32 HalSystemGetRunTimeMs(uint64 * resultMs_pu64) -{ - *resultMs_pu64 = systemStepCounter_gu64; - - return NMS_ERR_NONE; -} - - -void HalSystemGetSerialId(uint8 * serialIdBuffer_pu8) -{ - uint32 serialIdW0_u32, serialIdW1_u32, serialIdW2_u32; - - /* Get the three parts of the UID */ - serialIdW0_u32 = HAL_GetUIDw0(); - serialIdW1_u32 = HAL_GetUIDw1(); - serialIdW2_u32 = HAL_GetUIDw2(); - - /* Copy the values into the serial ID buffer */ - memcpy(&serialIdBuffer_pu8[0], &serialIdW0_u32, sizeof(serialIdW0_u32)); - memcpy(&serialIdBuffer_pu8[4], &serialIdW1_u32, sizeof(serialIdW1_u32)); - memcpy(&serialIdBuffer_pu8[8], &serialIdW2_u32, sizeof(serialIdW2_u32)); -} - - -uint32 HalSystemGetResetCause( HalSystemResetCauseEn resetCauseSelector_en, uint32 * causes_pu32 ) -{ - uint32 error_u32 = NMS_ERR_DEFAULT; - uint32 mask_u32 = 0uL; - - if (causes_pu32 == NULL) - { - error_u32 = NMS_ERR_NULL_POINTER; - } - else - { - switch(resetCauseSelector_en) - { - case HAL_SYSTEM_RESET_CAUSE_OPTION_BYTE_LOADER: - mask_u32 = RCC_CSR_OBLRSTF_Msk; - error_u32 = NMS_ERR_NONE; - break; - - case HAL_SYSTEM_RESET_CAUSE_EXTERNAL_PIN_RESET: - mask_u32 = RCC_CSR_PINRSTF_Msk; - error_u32 = NMS_ERR_NONE; - break; - - case HAL_SYSTEM_RESET_CAUSE_BROWNOUT_RESET: - mask_u32 = RCC_CSR_BORRSTF_Msk; - error_u32 = NMS_ERR_NONE; - break; - - case HAL_SYSTEM_RESET_CAUSE_SOFTWARE_RESET: - mask_u32 = RCC_CSR_SFTRSTF_Msk; - error_u32 = NMS_ERR_NONE; - break; - - case HAL_SYSTEM_RESET_CAUSE_WATCH_DOG_TIMER: - mask_u32 = RCC_CSR_IWDGRSTF_Msk; - error_u32 = NMS_ERR_NONE; - break; - - case HAL_SYSTEM_RESET_CAUSE_WINDOW_WATCH_DOG: - mask_u32 = RCC_CSR_WWDGRSTF_Msk; - error_u32 = NMS_ERR_NONE; - break; - - case HAL_SYSTEM_RESET_CAUSE_LOW_POWER: - mask_u32 = RCC_CSR_LPWRRSTF_Msk; - error_u32 = NMS_ERR_NONE; - break; - - case HAL_SYSTEM_RESET_CAUSE_ALL_CAUSES: - mask_u32 = RCC_CSR_IWDGRSTF_Msk - | RCC_CSR_WWDGRSTF_Msk - | RCC_CSR_SFTRSTF_Msk - | RCC_CSR_PINRSTF_Msk - | RCC_CSR_LPWRRSTF_Msk - | RCC_CSR_BORRSTF_Msk; - error_u32 = NMS_ERR_NONE; - break; - - default: - - error_u32 = NMS_ERR_UNKNOWN; - break; - } - - *causes_pu32 = resetStatusRegister_gu32 & mask_u32; - } - - return error_u32; -} - - -void HalSystemDisableInterrupts(void) -{ - __disable_irq(); -} - - -void HalSystemEnableInterrupts(void) -{ - __enable_irq(); -} - - -void HalSystemReset(void) -{ - HAL_NVIC_SystemReset(); -} - -/****************************************************************************** - * Callback Function Definitions - ******************************************************************************/ -/** -* @brief Count the number of milliseconds that elapsed since the start -* -* @note Function called by low-level functions of cubeMX -*/ -void HAL_IncTick(void) -{ - systemStepCounter_gu64++; -} - - -/** -* @brief Provides a tick value in millisecond. -* -* @return The number of elapsed tick. -*/ -uint32 HAL_GetTick(void) -{ - return (uint32)systemStepCounter_gu64; -} diff --git a/EnduranceTestBench/nms-hal/hal_system.h b/EnduranceTestBench/nms-hal/hal_system.h deleted file mode 100644 index daa1fc1..0000000 --- a/EnduranceTestBench/nms-hal/hal_system.h +++ /dev/null @@ -1,114 +0,0 @@ -/** - * @file hal_system.h - * @copyright Nehemis SARL reserves all rights even in the event of industrial - * property rights. We reserve all rights of disposal such as - * copying and passing on to third parties. - * - * - * @brief Header file for HAL layer for the SYSTEM module. - * - */ - -#ifndef INCLUDED_HAL_SYSTEM_H -#define INCLUDED_HAL_SYSTEM_H - -/****************************************************************************** - * Include Header Files - ******************************************************************************/ -#include "nms_types.h" - -/****************************************************************************** - * Macros Constant Declarations - ******************************************************************************/ -#define SERIAL_ID_BUFFER_SIZE 12 - -/****************************************************************************** - * Types Declarations - ******************************************************************************/ -typedef enum -{ - HAL_SYSTEM_RESET_CAUSE_OPTION_BYTE_LOADER, - HAL_SYSTEM_RESET_CAUSE_EXTERNAL_PIN_RESET, - HAL_SYSTEM_RESET_CAUSE_BROWNOUT_RESET, - HAL_SYSTEM_RESET_CAUSE_SOFTWARE_RESET, - HAL_SYSTEM_RESET_CAUSE_WATCH_DOG_TIMER, - HAL_SYSTEM_RESET_CAUSE_WINDOW_WATCH_DOG, - HAL_SYSTEM_RESET_CAUSE_LOW_POWER, - HAL_SYSTEM_RESET_CAUSE_ALL_CAUSES -} HalSystemResetCauseEn; /**< Enumeration used to analyze the reset cause location. */ - -/****************************************************************************** - * Global Variables Declarations - ******************************************************************************/ - -/****************************************************************************** - * Extern Functions Declarations - ******************************************************************************/ - -/** - * @brief Initializes the system HAL. - * - * @note CAUTION: This function must be called immediately after - * SystemClock_Config() in the main function to ensure correct - * operation and prevent potential software issues. - * - * @return Error code: 0 if successful, nonzero otherwise. - */ -uint32 HalSystemInit(void); - -/** - * @brief Retrieves the system runtime in microseconds. - * - * @param resultUs_pu64 Pointer to store the system runtime in microseconds. - * - * @note The tick resolution depends on the system tick frequency. - * - * @return Error code: 0 if successful, nonzero otherwise. - */ -uint32 HalSystemGetRunTimeUs(uint64 *resultUs_pu64); - -/** - * @brief Retrieves the system runtime in milliseconds. - * - * @param resultMs_pu64 Pointer to store the system runtime in milliseconds. - * - * @note The tick resolution depends on the system tick frequency. - * - * @return Error code: 0 if successful, nonzero otherwise. - */ -uint32 HalSystemGetRunTimeMs(uint64 *resultMs_pu64); - -/** - * @brief Disables all system interrupts. - */ -void HalSystemDisableInterrupts(void); - -/** - * @brief Enables all system interrupts. - */ -void HalSystemEnableInterrupts(void); - -/** - * @brief Retrieves the cause of the last system reset from the MCU registers. - * - * @param resetCauseSelector_en Enum specifying the reset cause type. - * causes_pu32 Pointer to store the corresponding bitmask value. - * - * @return Error code: 0 if successful, nonzero otherwise. - */ -uint32 HalSystemGetResetCause(HalSystemResetCauseEn resetCauseSelector_en, uint32 *causes_pu32); - -/** - * @brief Retrieves the system's unique serial ID. - * - * @param serialIdBuffer_pu8 Pointer to the buffer where the serial ID will be stored. - */ -void HalSystemGetSerialId(uint8 *serialIdBuffer_pu8); - -/** - * @brief Performs a software reset of the system. - */ -void HalSystemReset(void); - - -#endif /* INCLUDED_HAL_SYSTEM_H */ diff --git a/EnduranceTestBench/nms_can/nms_can.c b/EnduranceTestBench/nms_can/nms_can.c new file mode 100644 index 0000000..a3ae4ab --- /dev/null +++ b/EnduranceTestBench/nms_can/nms_can.c @@ -0,0 +1,574 @@ +/** + * @file nms_can.c + * + * @copyright Nehemis SARL reserves all rights even in the event of industrial + * property rights. We reserve all rights of disposal such as + * copying and passing on to third parties. + * + * @brief Source code for CANOpen files abstracted for furthur use in the project. + * + */ + +/****************************************************************************** + * Include Header Files + ******************************************************************************/ +#include "nms_can.h" +#include "enduranceTestBench.h" + +/* CANopen includes */ +#include +#include +#include "co_sdo.h" +#include "co_pdo.h" +#include "co_odaccess.h" + +/****************************************************************************** + * Global Variable Declaration + ******************************************************************************/ + +/****************************************************************************** + * Macro constant declarations + ******************************************************************************/ +#define NMS_CAN_CANOPEN_SLAVE_LINE 0u +#define NMS_CAN_CANOPEN_MASTER_LINE 1u + +#define NMS_CAN_CANOPEN_BITRATE 250u + +#define NMS_CAN_PU_MASTER_NODE_ID 1u +#define NMS_CAN_PU_SLAVE_NODE_ID 3u + +#define NMS_CAN_LSS_TIMEOUT 20u /* Defined in stack examples */ +#define NMS_CAN_LSS_CONFIG_TIMEOUT 1000u +#define NMS_CAN_LSS_CONFIG_INTERVAL 4u +#define NMS_CAN_APPL_TIMER_TIME 250000uL + +#define NMS_CAN_LSS_NODE_COUNT 10u +#define NMS_CAN_LSS_NODE_HB_MS 1000uL +#define NMS_CAN_LSS_NODE_STATE_RESET_INTERVAL 3u + +#define NMS_CAN_SDO_TRANSMIT 0x580u +#define NMS_CAN_SDO_RECEIVE 0x600u +#define NMS_CAN_SDO_PARAM_INDEX 0x1280u +#define NMS_LSS_NODE_COUNT 20u +/****************************************************************************** + * Type Declarations + ******************************************************************************/ +typedef struct +{ + uint32 vendorId_u32; + uint32 productId_u32; + uint32 versionNbr_u32; + uint32 serialNbr_u32; + uint8 nodeId_u8; +} SdlLssNodeInfo_t; +/****************************************************************************** + * Global Declarations + ******************************************************************************/ +SdlLssNodeInfo_t var_gst; +static CO_TIMER_T monitorTimer_gst; /**< application timer */ +static bool monitorSleep_gb = CO_FALSE; /**< sleep flag */ +static bool masterStarted_gb; /**< master started flag */ +static const SdlLssNodeInfo_t nodeLookupTable_gast[NMS_LSS_NODE_COUNT] = +{ + {0x319, 0x4d2, 0x1, 0x01, 0x5} , + {0x319, 0x4d2, 0x1, 0x02, 0x6} , + {0x319, 0x4d2, 0x1, 0x03, 0x7} , + {0x319, 0x4d2, 0x1, 0x04, 0x8} , + {0x319, 0x4d2, 0x1, 0x05, 0x9} , + {0x319, 0x4d2, 0x1, 0x06, 0xA} , + {0x319, 0x4d2, 0x1, 0x07, 0xB} , + {0x319, 0x4d2, 0x1, 0x08, 0xC} , + {0x319, 0x4d2, 0x1, 0x09, 0xD} , + {0x319, 0x4d2, 0x1, 0x0A, 0xE} , + {0x319, 0x4d2, 0x1, 0x0B, 0xF} , + {0x319, 0x4d2, 0x1, 0x0C, 0x10}, + {0x319, 0x4d2, 0x1, 0x0D, 0x11}, + {0x319, 0x4d2, 0x1, 0x0E, 0x12}, + {0x319, 0x4d2, 0x1, 0x0F, 0x13}, + {0x319, 0x4d2, 0x1, 0x10, 0x14}, + {0x319, 0x4d2, 0x1, 0x11, 0x15}, + {0x319, 0x4d2, 0x1, 0x12, 0x16}, + {0x319, 0x4d2, 0x1, 0x13, 0x17}, + {0x319, 0x4d2, 0x1, 0x14, 0x18} +}; +static CO_NMT_STATE_T nodeNMTState_gaen[NMS_LSS_NODE_COUNT]; +/****************************************************************************** + * Private Function Definition + ******************************************************************************/ + +static RET_T NmsCanOverwriteLoadIndication(uint8 index_u8); +static void NmsCanLssIndCallback( CO_LSS_MASTER_SERVICE_T service_en, uint16 errorCode_u16, uint8 errorSpec_u8, uint32 *pIdentity_pu32); +static void NmsCanLssHbMonitorCallback(uint8 nodeID_u8, CO_ERRCTRL_T state_en, CO_NMT_STATE_T nmtState_en); +static void NmsCanLssResetNodesCallback(void *pData_pv); /**< callback of reset handler */ +static uint8 NmsCanLssGetNodeIndex(uint8 nodeId_u8); +static void NmsCanLssToggleMonitorFlag(void *pData_pv); +static void NmsCanLssNodeHandlerRun(void); +static uint32 NmsCanLssConfigureNode(uint8 arrIndex_u8); +static RET_T NmsCanLssSetSdoCobID(uint8 sdoNr_u8, uint8 nodeId_u8); +/* Supress warnings for implicit declaration. + * Need this function for overwriting the manual COB ids + * for the TPDO. */ +extern void userOverwriteCobIdSettings(void); +/****************************************************************************** + * Extern Function Declarations + ******************************************************************************/ +void NmsCanInit() +{ + codrvHardwareInit(); + codrvCanInit(NMS_CANOPEN_BITRATE); + codrvTimerSetup(CO_TIMER_INTERVAL); + + /* CANopen Initialization */ + coCanOpenStackInit(NmsCanOverwriteLoadIndication); + coEventRegister_LSS_MASTER(NmsCanLssIndCallback); + coEventRegister_ERRCTRL(NmsCanLssHbMonitorCallback); + + /* Register SDO event handlers */ + coEventRegister_SDO_CLIENT_READ(EnduranceTestBenchReadInd); + coEventRegister_SDO_CLIENT_WRITE(EnduranceTestBenchWriteInd); + + /* enable CAN communication */ + codrvCanEnable(); + + coTimerStart(&monitorTimer_gst, NMS_CAN_APPL_TIMER_TIME, NmsCanLssToggleMonitorFlag, NULL, CO_TIMER_ATTR_ROUNDUP_CYCLIC); + coLssIdentifyNonConfiguredSlaves(NMS_CAN_LSS_CONFIG_TIMEOUT, NMS_CAN_LSS_CONFIG_INTERVAL); + + /* node == 0, the NMT request is sent to all nodes. */ + coNmtStateReq(NMS_CAN_PU_MASTER_NODE_ID, CO_NMT_STATE_OPERATIONAL, CO_TRUE); +} + + +void NmsCanRun(void) +{ + coCommTask(); + + /* LSS main runner */ + NmsCanLssNodeHandlerRun(); +} + + +uint32 NmsCanGetObj_u8(uint16 index_u16, uint8 subIndex_u8, uint8 *pObj_pu8) +{ + uint32 error_u32 = NMS_ERR_DEFAULT; + + RET_T retVal_en = coOdGetObj_u8(index_u16, subIndex_u8, pObj_pu8); + if ( retVal_en == RET_OK) + { + error_u32 = NMS_ERR_NONE; + } + + return error_u32; +} + + +uint32 NmsCanGetObj_u32(uint16 index_u16, uint8 subIndex_u8, uint32 *pObj_pu32) +{ + uint32 error_u32 = NMS_ERR_DEFAULT; + + RET_T retVal_en = coOdGetObj_u32(index_u16, subIndex_u8, pObj_pu32); + if ( retVal_en == RET_OK) + { + error_u32 = NMS_ERR_NONE; + } + + return error_u32; +} + + +uint32 NmsCanGetObj_f32(uint16 index_u16, uint8 subIndex_u8, float32 *pObj_pf32) +{ + uint32 error_u32 = NMS_ERR_DEFAULT; + + RET_T retVal_en = coOdGetObj_r32(index_u16, subIndex_u8, pObj_pf32); + if ( retVal_en == RET_OK) + { + error_u32 = NMS_ERR_NONE; + } + + return error_u32; +} + + +uint32 NmsCanPutObj_u8(uint16 index_u16, uint8 subIndex_u8, uint8 newVal_u8) +{ + uint32 error_u32 = NMS_ERR_DEFAULT; + + RET_T retVal_en = coOdPutObj_u8(index_u16, subIndex_u8, newVal_u8); + if ( retVal_en == RET_OK) + { + error_u32 = NMS_ERR_NONE; + } + + return error_u32; +} + + +uint32 NmsCanPutObj_u32(uint16 index_u16, uint8 subIndex_u8, uint32 newVal_u32) +{ + uint32 error_u32 = NMS_ERR_DEFAULT; + + RET_T retVal_en = coOdPutObj_u32(index_u16, subIndex_u8, newVal_u32); + if ( retVal_en == RET_OK) + { + error_u32 = NMS_ERR_NONE; + } + + return error_u32; +} + + +uint32 NmsCanPutObj_f32(uint16 index_u16, uint8 subIndex_u8, uint32 newVal_u32) +{ + uint32 error_u32 = NMS_ERR_DEFAULT; + + RET_T retVal_en = coOdPutObj_r32(index_u16, subIndex_u8, newVal_u32); + if ( retVal_en == RET_OK) + { + error_u32 = NMS_ERR_NONE; + } + + return error_u32; +} +/****************************************************************************** + * Private Function Definitions + ******************************************************************************/ +/** + * @brief Handler for the defined nodes in the network. + * This function starts the configuration of a node if needed + * + * @return void + * + */ +static void NmsCanLssNodeHandlerRun(void) +{ + if (monitorSleep_gb != CO_TRUE) + { + for (uint8 i_u8 = 0u; i_u8 < NMS_CAN_LSS_NODE_COUNT; i_u8++) + { + if (nodeNMTState_gaen[i_u8] == CO_NMT_STATE_PREOP) + { + NmsCanLssConfigureNode(i_u8); + } + if (nodeNMTState_gaen[i_u8] == CO_NMT_STATE_OPERATIONAL) + { + /* Do nothing */ + } + } + } + monitorSleep_gb = CO_TRUE; +} + + +/** + * @brief Load function for overwriting the TPDO COB id values. + * + * @param index_u8 Subindex parameter to point parameter area(unused) + * canLine_u8 The canline MASTER or SLAVE + * + * @return Error Code + */ +static RET_T NmsCanOverwriteLoadIndication(uint8 index_u8) +{ + userOverwriteCobIdSettings(); + + return RET_OK; +} + + +/** + * @brief This function is called if a new NMT state of a node, + * is recordnized by the CANopen stack. + * + * @param nodeID_u8 Node id of the node that has registered a change. + * state_en Error control state + * nmtState_en NMT state of the particular node. + * + * @return Array index of the node in the network. + * + */ +static uint8 NmsCanLssGetNodeIndex(uint8 nodeId_u8) +{ + uint8 arrIndex_u8; + + /* find node ID array arrIndex_u8 */ + for (arrIndex_u8 = 0u; arrIndex_u8 < NMS_CAN_LSS_NODE_COUNT; arrIndex_u8++) + { + if (nodeId_u8 == nodeLookupTable_gast[arrIndex_u8].nodeId_u8) + { + return arrIndex_u8; + } + } + + return NMS_UINT8_MAX; +} + + +/** + * @brief This function is called when a new NMT state of a node + * is recognized by the CANopen stack. + * + * @param canLine_u8 Indicates whether the node is on the MASTER or SLAVE CAN line. + * pData Pointer to additional data (unused). + */ +static void NmsCanLssToggleMonitorFlag(void *pData_pv) +{ + (void)pData_pv; + + /* deactivate application sleep flag */ + monitorSleep_gb = CO_FALSE; +} + + +/** +* @brief Configure a specific node. +* This function adds the defined node to heartbeat consumers, +* and sets its heartbeat interval. +* +* @param arrIndex_u8 Index of the node in the array which is to be configured. +* +* @return Status of the operation. +* +*/ +static uint32 NmsCanLssConfigureNode(uint8 arrIndex_u8) +{ + uint32 error_u32 = NMS_ERR_DEFAULT; + RET_T retVal_en = RET_INTERNAL_ERROR; + + /* Get the node ID from the lookup table using arrIndex_u8 */ + uint8 nodeId_u8 = nodeLookupTable_gast[arrIndex_u8].nodeId_u8; + + /* Add node to hb consumers with +25% tolerance + * Rationale - Allows some flexibility in detecting timeouts due to minor clock drifts, + * bus delays, or transmission issues.*/ + retVal_en = coHbConsumerSet(nodeId_u8, + ((NMS_CAN_LSS_NODE_HB_MS / 100 * 25) + NMS_CAN_LSS_NODE_HB_MS)); + retVal_en = coHbConsumerStart(nodeId_u8); + + /* setup SDO channel */ + retVal_en = NmsCanLssSetSdoCobID((arrIndex_u8 + 1), nodeLookupTable_gast[arrIndex_u8].nodeId_u8); + + //retVal_en = coSdoWrite(NmsCan_CANOPEN_MASTER_LINE, (arrIndex_u8 + 1), 0x1017u, 0u, (uint8*)(&nodeHBs[0]), 2u, CO_FALSE, 1000u); + + /* start node */ + retVal_en = coNmtStateReq(nodeId_u8, CO_NMT_STATE_OPERATIONAL, CO_FALSE); + if (retVal_en != RET_OK) + { + error_u32 = NMS_LSS_NODE_CONFIG_ERROR; + } + /* set local state to operational, if not operational yet */ + if (masterStarted_gb == CO_FALSE) + { + /* set local state */ + coNmtLocalStateReq(CO_NMT_STATE_OPERATIONAL); + + /* save started flag */ + masterStarted_gb = CO_TRUE; + } + + return error_u32; +} + + +/****************************************************************************** + * Callback Function Definitions + ******************************************************************************/ +/** + * @brief LSS indication function for handling the LSS api calls for dynamic + * setup of node ids. + * + * @param canLine_u8 The canline MASTER or SLAVE + * service_en LSS master services for indication functions + * errorCode_u16 Error code in the module + * errorSpec_u8 Specific error case that has occured + * pIdentity_pu32 LSS slave identity. + * + */ +static void NmsCanLssIndCallback(CO_LSS_MASTER_SERVICE_T service_en, uint16 errorCode_u16, uint8 errorSpec_u8, uint32 *pIdentity_pu32) +{ + static uint8 matchedIndex_u8 = NMS_UINT8_MAX; + + if (errorCode_u16 != 0u) + { + if (errorCode_u16 == NMS_UINT16_MAX) + { + /* ERROR */ + } + else + { + /* ERROR */ + } + + if (service_en == CO_LSS_MASTER_SERVICE_STORE) + { + /* DEBUG INFO */ + coLssSwitchGlobal(CO_LSS_STATE_WAITING); + } + return; + } + + switch (service_en) + { + case CO_LSS_MASTER_SERVICE_NON_CONFIG_SLAVE: + /* DEBUG INFO */ + coLssFastScan(NMS_CAN_LSS_TIMEOUT); + break; + + case CO_LSS_MASTER_SERVICE_FASTSCAN: + /* Match detected node with lookup table */ + for (uint8 i_u8 = 0; i_u8 < NMS_CAN_LSS_NODE_COUNT; i_u8++) + { + if (pIdentity_pu32[0] == nodeLookupTable_gast[i_u8].vendorId_u32 && + pIdentity_pu32[1] == nodeLookupTable_gast[i_u8].productId_u32 && + pIdentity_pu32[2] == nodeLookupTable_gast[i_u8].versionNbr_u32 && + pIdentity_pu32[3] == nodeLookupTable_gast[i_u8].serialNbr_u32) + { + coLssSwitchSelective(pIdentity_pu32[0], pIdentity_pu32[1], + pIdentity_pu32[2], pIdentity_pu32[3], 20); + matchedIndex_u8 = i_u8; + break; + } + } + break; + + case CO_LSS_MASTER_SERVICE_SWITCH_SELECTIVE: + if (matchedIndex_u8 < NMS_CAN_LSS_NODE_COUNT) + { + coLssSetNodeId(nodeLookupTable_gast[matchedIndex_u8].nodeId_u8, NMS_CAN_LSS_TIMEOUT); + matchedIndex_u8 = NMS_UINT8_MAX; + } + else + { + /* ERROR */ + } + break; + + case CO_LSS_MASTER_SERVICE_SET_NODEID: + /* DEBUG INFO */ + coLssInquireNodeId(NMS_CAN_LSS_TIMEOUT); + break; + + case CO_LSS_MASTER_SERVICE_INQUIRE_NODEID: + /* DEBUG INFO */ + coLssStoreConfig( 200); + break; + + case CO_LSS_MASTER_SERVICE_STORE: + /* DEBUG INFO */ + coLssSwitchGlobal(CO_LSS_STATE_WAITING); + break; + + default: + /* ERROR */ + break; + } +} + + +/** + * @brief This function is called if a new NMT state of a node, + * is recordnized by the CANopen stack. + * + * @param nodeID_u8 Node id of the node that has registered a change. + * state_en Error control state + * nmtState_en NMT state of the particular node. + * + * @return void + * + */ +static void NmsCanLssHbMonitorCallback(uint8 nodeID_u8, CO_ERRCTRL_T state_en, CO_NMT_STATE_T nmtState_en) +{ + uint8 arrIndex_u8; + + /* look if node is monitored */ + arrIndex_u8 = NmsCanLssGetNodeIndex(nodeID_u8); + + /* handle monitored node */ + if (arrIndex_u8 != NMS_UINT16_MAX) + { + /* save states */ + nodeNMTState_gaen[arrIndex_u8] = nmtState_en; + + /* indicate if monitored node lost heartbeat */ + if (nmtState_en == CO_NMT_STATE_UNKNOWN) + { + /* To be transmitted via CAN */ + /* ERROR */ + } + + /* indicate if monitored node sent a bootup message */ + if (state_en == CO_ERRCTRL_BOOTUP) + { + /* INFO */ + } + + /* handle unmonitored node */ + } + else + { + /* ERROR */ + } +} + + +/** +* @brief This function tries to reset nodes with unknown NMT state. +* +* @param pData_pv Data. +*/ +static void NmsCanLssResetNodesCallback(void *pData_pv) +{ + uint8 arrIndex_u8; + + (void)pData_pv; + + /* reset defined nodes without known state */ + for (arrIndex_u8 = 0u; arrIndex_u8 < 3; arrIndex_u8++) + { + if ((nodeNMTState_gaen[arrIndex_u8] != CO_NMT_STATE_PREOP) && + (nodeNMTState_gaen[arrIndex_u8] != CO_NMT_STATE_OPERATIONAL)) + { + /* reset node */ + coNmtStateReq(nodeLookupTable_gast[arrIndex_u8].nodeId_u8, CO_NMT_STATE_RESET_NODE, CO_FALSE); + } + } +} + + +/** +* @brief This function configures a SDO client for the +* given node ID and SDO number. +* +* @param sdoNr_u8 Sdo number +* nodeId_u8 Node id of the node. +* +* @return Error state. +* +*/ +static RET_T NmsCanLssSetSdoCobID(uint8 sdoNr_u8, uint8 nodeId_u8) +{ + uint16 cobIndex_u16; + uint32 newCobId_u32; + RET_T retVal = RET_INTERNAL_ERROR; + + /* get od index of sdoNr */ + cobIndex_u16 = NMS_CAN_SDO_PARAM_INDEX + sdoNr_u8 - 1u; + + /* set cobID for client to server direction (request) */ + newCobId_u32 = NMS_CAN_SDO_RECEIVE + nodeId_u8; + retVal = coOdSetCobid(cobIndex_u16, 1u, newCobId_u32); + + if (retVal == RET_OK) + { + /* set cobID for server to client direction (response) */ + newCobId_u32 = NMS_CAN_SDO_TRANSMIT + nodeId_u8; + retVal = coOdSetCobid(cobIndex_u16, 2u, newCobId_u32); + } + + /* print failed setup details */ + if (retVal != RET_OK) + { + /* ERROR */ + } + + return retVal; +} diff --git a/EnduranceTestBench/nms_can/nms_can.h b/EnduranceTestBench/nms_can/nms_can.h new file mode 100644 index 0000000..a0a270f --- /dev/null +++ b/EnduranceTestBench/nms_can/nms_can.h @@ -0,0 +1,108 @@ +/** + * @file nms_can.h + * + * @copyright Nehemis SARL reserves all rights even in the event of industrial + * property rights. We reserve all rights of disposal such as + * copying and passing on to third parties. + * + * @brief CANOpen files abstracted for furthur use in the project. + * + */ + +#ifndef NMS_CAN_H_ +#define NMS_CAN_H_ + +/****************************************************************************** + * Include Header Files + ******************************************************************************/ +#include "nms_types.h" +#include "co_datatype.h" +#include "co_nmt.h" +/****************************************************************************** + * Macro constant declarations + ******************************************************************************/ +#define NMS_CANOPEN_BITRATE 250u +/****************************************************************************** + * Extern Function Declarations + ******************************************************************************/ +/** + * @brief Initializes the CAN controller and CANopen stack. + */ +void NmsCanInit(void); + +/** + * @brief Runs the CAN communication tasks. + * + * @param canLine_u8 Can line selected. + */ +void NmsCanRun(void); + +/** + * @brief Retrieves a 8-bit object from the CANopen object dictionary. + * + * @param index_u16 The object dictionary index. + * subIndex_u8 The sub-index of the object. + * pObj_pu8 Pointer to store the retrieved object value. + * canLine_u8 Can line selected. + * + * @return Error code. (NMS_ERR_NONE if successful, or an error code). + */ +uint32 NmsCanGetObj_u8(uint16 index_u16, uint8 subIndex_u8, uint8 *pObj_pu8); + +/** + * @brief Retrieves a 32-bit object from the CANopen object dictionary. + * + * @param index_u16 The object dictionary index. + * subIndex_u8 The sub-index of the object. + * pObj_pu8 Pointer to store the retrieved object value. + * + * @return Error code. (NMS_ERR_NONE if successful, or an error code). + */ +uint32 NmsCanGetObj_u32(uint16 index_u16, uint8 subIndex_u8, uint32 *pObj_pu32); + +/** + * @brief Retrieves a float object from the CANopen object dictionary. + * + * @param index_u16 The object dictionary index. + * subIndex_u8 The sub-index of the object. + * pObj_f32 Pointer to store the retrieved object value. + * + * @return Error code. (NMS_ERR_NONE if successful, or an error code). + */ +uint32 NmsCanGetObj_f32(uint16 index_u16, uint8 subIndex_u8, float32 *pObj_pf32); + +/** + * @brief Puts a 8-bit object in the CANopen object dictionary. + * + * @param index_u16 The object dictionary index. + * subIndex_u8 The sub-index of the object. + * newVal_u32 The new value to be set. + * + * @return Error code. (NMS_ERR_NONE if successful, or an error code). + */ +uint32 NmsCanPutObj_u8(uint16 index_u16, uint8 subIndex_u8, uint8 newVal_u8); + +/** + * @brief Puts a 32-bit object in the CANopen object dictionary. + * + * @param index_u16 The object dictionary index. + * subIndex_u8 The sub-index of the object. + * newVal_u32 The new value to be set. + * + * @return Error code. (NMS_ERR_NONE if successful, or an error code). + */ +uint32 NmsCanPutObj_u32(uint16 index_u16, uint8 subIndex_u8, uint32 newVal_u32); + +/** + * @brief Puts a float object in the CANopen object dictionary. + * + * @param index_u16 The object dictionary index. + * subIndex_u8 The sub-index of the object. + * newVal_u32 The new value to be set. + * + * @return Error code. (NMS_ERR_NONE if successful, or an error code). + */ +uint32 NmsCanPutObj_f32(uint16 index_u16, uint8 subIndex_u8, uint32 newVal_u32); + + +#endif /* NMS_CAN_H_ */ diff --git a/EnduranceTestBench/scheduler/sdl.c b/EnduranceTestBench/scheduler/sdl.c index 16316aa..5d37a70 100644 --- a/EnduranceTestBench/scheduler/sdl.c +++ b/EnduranceTestBench/scheduler/sdl.c @@ -17,105 +17,29 @@ /****************************************************************************** * Include Header Files ******************************************************************************/ -/* CANopen includes */ -#include -#include -#include -#include "co_sdo.h" -#include "co_odaccess.h" - /* User includes */ #include "sdl.h" +#include "nms_can.h" #include "processBoard.h" #include "enduranceTestBench.h" -#include "hal_system.h" - #include "stdlib.h" +#include "hal_system.h" /****************************************************************************** * Macro constant declarations ******************************************************************************/ -#define SDL_CANOPEN_BITRATE 250u -#define SDL_PU_MASTER_NODE_ID 1u -#define SDL_LSS_TIMEOUT 20u /* Defined in stack examples */ -#define SDL_LSS_CONFIG_TIMEOUT 1000u -#define SDL_LSS_CONFIG_INTERVAL 4u -#define SDL_APPL_TIMER_TIME 250000uL -#define SDL_LSS_NODE_COUNT 20u -#define SDL_LSS_NODE_HB_MS 1000uL -#define SDL_LSS_NODE_STATE_RESET_INTERVAL 3u - -#define SDL_TEST_BENCH_SDO_TIMEOUT 1000u -#define SDL_TEST_BENCH_STARTUP_TIMEOUT 10000uLL - -#define SDL_POSITION_SETPOINT_INDEX 0x6002 -#define SDL_POSITION_SETPOINT_SUB_INDEX 0x0 -#define SDL_POSITION_FEEDBACK_INDEX 0x6004 -#define SDL_POSITION_FEEDBACK_SUB_INDEX 0x0 - -#define SDL_SDO_CLIENT_COB 0x1280 -#define SDL_SDO_CLIENT_TO_SERVER_COB 0x600 -#define SDL_SDO_SERVER_TO_CLIENT_COB 0x580 - #define SDL_MIN_OPERATIONAL_NODES 18u /* To be 20, one node not in working state currently */ +#define SDL_LSS_NODE_COUNT 20u /****************************************************************************** * Type Declarations ******************************************************************************/ -typedef struct -{ - uint32 vendorId_u32; - uint32 productId_u32; - uint32 versionNbr_u32; - uint32 serialNbr_u32; - uint8 nodeId_u8; -} SdlLssNodeInfo_t; /****************************************************************************** * Global Declarations ******************************************************************************/ -SdlLssNodeInfo_t var_gst; -static CO_TIMER_T monitorTimer_gst; /**< application timer */ -static CO_TIMER_T nodeResetTimer_gst; /**< node reset timer */ -static bool monitorSleep_gb = CO_FALSE; /**< sleep flag */ -static bool masterStarted_gb; /**< master started flag */ -static const SdlLssNodeInfo_t nodeLookupTable_gast[SDL_LSS_NODE_COUNT] = -{ - {0x319, 0x4d2, 0x1, 0x01, 0x5} , - {0x319, 0x4d2, 0x1, 0x02, 0x6} , - {0x319, 0x4d2, 0x1, 0x03, 0x7} , - {0x319, 0x4d2, 0x1, 0x04, 0x8} , - {0x319, 0x4d2, 0x1, 0x05, 0x9} , - {0x319, 0x4d2, 0x1, 0x06, 0xA} , - {0x319, 0x4d2, 0x1, 0x07, 0xB} , - {0x319, 0x4d2, 0x1, 0x08, 0xC} , - {0x319, 0x4d2, 0x1, 0x09, 0xD} , - {0x319, 0x4d2, 0x1, 0x0A, 0xE} , - {0x319, 0x4d2, 0x1, 0x0B, 0xF} , - {0x319, 0x4d2, 0x1, 0x0C, 0x10}, - {0x319, 0x4d2, 0x1, 0x0D, 0x11}, - {0x319, 0x4d2, 0x1, 0x0E, 0x12}, - {0x319, 0x4d2, 0x1, 0x0F, 0x13}, - {0x319, 0x4d2, 0x1, 0x10, 0x14}, - {0x319, 0x4d2, 0x1, 0x11, 0x15}, - {0x319, 0x4d2, 0x1, 0x12, 0x16}, - {0x319, 0x4d2, 0x1, 0x13, 0x17}, - {0x319, 0x4d2, 0x1, 0x14, 0x18} -}; static CO_NMT_STATE_T nodeNMTState_gaen[SDL_LSS_NODE_COUNT]; - /****************************************************************************** * Static function Declarations ******************************************************************************/ -static void SdlInitCanopen(void); -static void SdlRunCanopen(void); -static RET_T SdlOverwriteLoadIndication(uint8 index_u8); -static void SdlLssIndCallback(CO_LSS_MASTER_SERVICE_T service_en, uint16 errorCode_u16, uint8 errorSpec_u8, uint32 *pIdentity_pu32); -static void SdlLssHbMonitorCallback(uint8 nodeID_u8, CO_ERRCTRL_T state_en, CO_NMT_STATE_T nmtState_en); -static void SdlLssResetNodesCallback(void *pData_pv); /**< callback of reset handler */ -static uint8 SdlLssGetNodeIndex(uint8 nodeId_u8); -static void SdlLssToggleMonitorFlag(void *pData); -static void SdlLssNodeHandlerRun(void); -static uint32 SdlLssConfigureNode(uint8 arrIndex_u8); -static RET_T SdlLssSetSdoCobID(uint8 sdoNr_u8, uint8 nodeId_u8); /* Supress warnings for implicit declaration. * Need this function for overwriting the manual COB ids * for the TPDO. */ @@ -127,246 +51,24 @@ static bool SdlAreAllNodesOperational(void); ******************************************************************************/ void SdlInit(void) { - SdlInitCanopen(); + HalSystemInit(); + NmsCanInit(); } void SdlRun(void) { - SdlRunCanopen(); - SdlLssNodeHandlerRun(); + NmsCanRun(); if (SdlAreAllNodesOperational()) { EnduranceTestBenchRun(); + ProcessBoardRun(); } } - -/****************************************************************************** - * Private Function Declarations - ******************************************************************************/ -/** - * @brief Init the CANopen stack. - * - */ -static void SdlInitCanopen(void) -{ - RET_T retval; - HalSystemInit(); - codrvHardwareInit(); - retval = codrvCanInit(SDL_CANOPEN_BITRATE); - retval = codrvTimerSetup(CO_TIMER_INTERVAL); - - /* CANopen Initialization */ - retval = coCanOpenStackInit(SdlOverwriteLoadIndication); - retval = coEventRegister_LSS_MASTER(SdlLssIndCallback); - retval = coEventRegister_ERRCTRL(SdlLssHbMonitorCallback); - - /* Register SDO event handlers */ - coEventRegister_SDO_CLIENT_READ(EnduranceTestBenchReadInd); - coEventRegister_SDO_CLIENT_WRITE(EnduranceTestBenchWriteInd); - - /* enable CAN communication */ - retval = codrvCanEnable(); - retval = coTimerStart(&monitorTimer_gst, SDL_APPL_TIMER_TIME, SdlLssToggleMonitorFlag, NULL, CO_TIMER_ATTR_ROUNDUP_CYCLIC); - //retval = coTimerStart(&nodeResetTimer_gst, (SDL_LSS_NODE_STATE_RESET_INTERVAL * 1000000uLL), SdlLssResetNodesCallback, NULL, CO_TIMER_ATTR_ROUNDUP_CYCLIC); - - coLssIdentifyNonConfiguredSlaves(SDL_LSS_CONFIG_TIMEOUT, SDL_LSS_CONFIG_INTERVAL); - retval = coNmtStateReq(SDL_PU_MASTER_NODE_ID, CO_NMT_STATE_OPERATIONAL, CO_TRUE); -} - - -/** - * @brief Runs the CANopen stack. - * - */ -static void SdlRunCanopen(void) -{ - coCommTask(); - SdlLssNodeHandlerRun(); -} - - /****************************************************************************** * Private Function Definitions ******************************************************************************/ -/** - * @brief Handler for the defined nodes in the network. - * This function starts the configuration of a node if needed - * - * @return void - * - */ -static void SdlLssNodeHandlerRun(void) -{ - if (monitorSleep_gb != CO_TRUE) - { - for (uint8 i_u8 = 0u; i_u8 < SDL_LSS_NODE_COUNT; i_u8++) - { - if (nodeNMTState_gaen[i_u8] == CO_NMT_STATE_PREOP) - { - SdlLssConfigureNode(i_u8); - } - if (nodeNMTState_gaen[i_u8] == CO_NMT_STATE_OPERATIONAL) - { - /* Do nothing */ - } - } - } - monitorSleep_gb = CO_TRUE; -} - - -/** - * @brief Load function for overwriing the TPDO COB id values. - * - * @param index_u8 Subindex parameter to point parameter area(unused) - * - * @return Error Code - */ -static RET_T SdlOverwriteLoadIndication(uint8 index_u8) -{ - userOverwriteCobIdSettings(); - - return RET_OK; -} - - -/** - * @brief This function is called if a new NMT state of a node, - * is recordnized by the CANopen stack. - * - * @param nodeID_u8 Node id of the node that has registered a change. - * state_en Error control state - * nmtState_en NMT state of the particular node. - * - * @return Array index of the node in the network. - * - */ -static uint8 SdlLssGetNodeIndex(uint8 nodeId_u8) -{ - uint8 arrIndex_u8; - - /* find node ID array arrIndex_u8 */ - for (arrIndex_u8 = 0u; arrIndex_u8 < SDL_LSS_NODE_COUNT; arrIndex_u8++) - { - if (nodeId_u8 == nodeLookupTable_gast[arrIndex_u8].nodeId_u8) - { - return arrIndex_u8; - } - } - - return NMS_UINT8_MAX; -} - - -/** - * @brief This function is called if a new NMT state of a node, - * is recordnized by the CANopen stack. - * - * @param nodeID_u8 Node id of the node that has registered a change. - * state_en Error control state - * nmtState_en NMT state of the particular node. - * - * @return Array index of the node in the network. - * - */ -static void SdlLssToggleMonitorFlag(void *pData) -{ - (void)pData; - - /* deactivate application sleep flag */ - monitorSleep_gb = CO_FALSE; -} - - -/** -* @brief Configure a specific node. -* This function adds the defined node to heartbeat consumers, -* and sets its heartbeat interval. -* -* @param arrIndex_u8 Index of the node in the array which is to be configured. -* -* @return Status of the operation. -* -*/ -static uint32 SdlLssConfigureNode(uint8 arrIndex_u8) -{ - uint32 error_u32 = SDL_DEFAULT_ERROR; - RET_T retVal_en = RET_INTERNAL_ERROR; - - /* Get the node ID from the lookup table using the index passed */ - uint8 nodeId_u8 = nodeLookupTable_gast[arrIndex_u8].nodeId_u8; - - /* Add node to heartbeat consumers with +25% tolerance - * Rationale - Allows some flexibility in detecting timeouts due to minor clock drifts, - * bus delays, or transmission issues.*/ - retVal_en = coHbConsumerSet(nodeId_u8, - ((SDL_LSS_NODE_HB_MS / 100u * 25u) + SDL_LSS_NODE_HB_MS)); - retVal_en = coHbConsumerStart(nodeId_u8); - - /* setup SDO channel */ - retVal_en = SdlLssSetSdoCobID((arrIndex_u8 + 1u), nodeLookupTable_gast[arrIndex_u8].nodeId_u8); - - /* start node */ - retVal_en = coNmtStateReq(nodeId_u8, CO_NMT_STATE_OPERATIONAL, CO_FALSE); - if (retVal_en != RET_OK) - { - error_u32 = SDL_LSS_NODE_CONFIG_ERROR; - } - /* set local state to operational, if not operational yet */ - if (masterStarted_gb == CO_FALSE) - { - /* set local state */ - coNmtLocalStateReq(CO_NMT_STATE_OPERATIONAL); - - /* save started flag */ - masterStarted_gb = CO_TRUE; - } - - return error_u32; -} - - -/** -* @brief This function configures a SDO client for the -* given node ID and SDO number. -* -* @param sdoNr_u8 Sdo number -* nodeId_u8 Node id of the node. -* -* @return Error state. -* -*/ -static RET_T SdlLssSetSdoCobID(uint8 sdoNr_u8, uint8 nodeId_u8) -{ - uint16 cobIndex_u16; - uint32 newCobId_u32; - RET_T retVal_en = RET_INTERNAL_ERROR; - - /* get od index of sdoNr */ - cobIndex_u16 = SDL_SDO_CLIENT_COB + sdoNr_u8 - 1u; /* SDO starts from 1280 index */ - - /* set cobID for client to server direction (request) */ - newCobId_u32 = SDL_SDO_CLIENT_TO_SERVER_COB + nodeId_u8; - retVal_en = coOdSetCobid(cobIndex_u16, 1u, newCobId_u32); - - if (retVal_en == RET_OK) - { - /* set cobID for server to client direction (response) */ - newCobId_u32 = SDL_SDO_SERVER_TO_CLIENT_COB + nodeId_u8; - retVal_en = coOdSetCobid(cobIndex_u16, 2u, newCobId_u32); - } - - /* print failed setup details */ - if (retVal_en != RET_OK) - { - /* ERROR */ - } - - return retVal_en; -} - /** * @brief Checks if all nodes are in OPERATIONAL state. @@ -387,166 +89,3 @@ static bool SdlAreAllNodesOperational(void) return (operationalNodeNb_u8 >= SDL_MIN_OPERATIONAL_NODES) ? CO_TRUE : CO_FALSE; } -/****************************************************************************** - * Callback Function Definitions - ******************************************************************************/ -/** - * @brief LSS indication function for handling the LSS api calls for dynamic - * setup of node ids. - * - * @param service_en LSS master services for indication functions - * errorCode_u16 Error code in the module - * errorSpec_u8 Specific error case that has occured - * pIdentity_pu32 LSS slave identity. - * - */ -static void SdlLssIndCallback(CO_LSS_MASTER_SERVICE_T service_en, uint16 errorCode_u16, uint8 errorSpec_u8, uint32 *pIdentity_pu32) -{ - static uint8 matchedIndex_u8 = NMS_UINT8_MAX; - - if (errorCode_u16 != 0u) - { - if (errorCode_u16 == NMS_UINT16_MAX) - { - /* ERROR */ - } - else - { - /* ERROR */ - } - - if (service_en == CO_LSS_MASTER_SERVICE_STORE) - { - /* DEBUG INFO */ - coLssSwitchGlobal(CO_LSS_STATE_WAITING); - } - return; - } - - switch (service_en) - { - case CO_LSS_MASTER_SERVICE_NON_CONFIG_SLAVE: - /* DEBUG INFO */ - coLssFastScan(SDL_LSS_TIMEOUT); - break; - - case CO_LSS_MASTER_SERVICE_FASTSCAN: - /* Match detected node with lookup table */ - for (uint8 i_u8 = 0u; i_u8 < SDL_LSS_NODE_COUNT; i_u8++) - { - if (pIdentity_pu32[0] == nodeLookupTable_gast[i_u8].vendorId_u32 && - pIdentity_pu32[1] == nodeLookupTable_gast[i_u8].productId_u32 && - pIdentity_pu32[2] == nodeLookupTable_gast[i_u8].versionNbr_u32 && - pIdentity_pu32[3] == nodeLookupTable_gast[i_u8].serialNbr_u32) - { - coLssSwitchSelective(pIdentity_pu32[0], pIdentity_pu32[1], - pIdentity_pu32[2], pIdentity_pu32[3], 20); - matchedIndex_u8 = i_u8; - break; - } - } - break; - - case CO_LSS_MASTER_SERVICE_SWITCH_SELECTIVE: - if (matchedIndex_u8 < SDL_LSS_NODE_COUNT) - { - coLssSetNodeId(nodeLookupTable_gast[matchedIndex_u8].nodeId_u8, SDL_LSS_TIMEOUT); - matchedIndex_u8 = NMS_UINT8_MAX; - } - else - { - /* ERROR */ - } - break; - - case CO_LSS_MASTER_SERVICE_SET_NODEID: - /* DEBUG INFO */ - coLssInquireNodeId(SDL_LSS_TIMEOUT); - break; - - case CO_LSS_MASTER_SERVICE_INQUIRE_NODEID: - /* DEBUG INFO */ - coLssStoreConfig(200); - break; - - case CO_LSS_MASTER_SERVICE_STORE: - /* DEBUG INFO */ - coLssSwitchGlobal(CO_LSS_STATE_WAITING); - break; - - default: - /* ERROR */ - break; - } -} - - -/** - * @brief This function is called if a new NMT state of a node, - * is recordnized by the CANopen stack. - * - * @param nodeID_u8 Node id of the node that has registered a change. - * state_en Error control state - * nmtState_en NMT state of the particular node. - * - * @return void - * - */ -static void SdlLssHbMonitorCallback(uint8 nodeID_u8, CO_ERRCTRL_T state_en, CO_NMT_STATE_T nmtState_en) -{ - uint8 arrIndex_u8; - - /* look if node is monitored */ - arrIndex_u8 = SdlLssGetNodeIndex(nodeID_u8); - - /* handle monitored node */ - if (arrIndex_u8 != NMS_UINT16_MAX) - { - /* save states */ - nodeNMTState_gaen[arrIndex_u8] = nmtState_en; - - /* indicate if monitored node lost heartbeat */ - if (nmtState_en == CO_NMT_STATE_UNKNOWN) - { - /* To be transmitted via CAN */ - /* ERROR */ - } - - /* indicate if monitored node sent a bootup message */ - if (state_en == CO_ERRCTRL_BOOTUP) - { - /* INFO */ - } - - /* handle unmonitored node */ - } - else - { - /* ERROR */ - } -} - - -/** -* @brief This function tries to reset nodes with unknown NMT state. -* -* @param pData_pv Data. -*/ -static void SdlLssResetNodesCallback(void *pData_pv) -{ - uint8 arrIndex_u8; - - (void)pData_pv; - - /* reset defined nodes without known state */ - for (arrIndex_u8 = 0u; arrIndex_u8 < SDL_LSS_NODE_COUNT; arrIndex_u8++) - { - if ((nodeNMTState_gaen[arrIndex_u8] != CO_NMT_STATE_PREOP) && - (nodeNMTState_gaen[arrIndex_u8] != CO_NMT_STATE_OPERATIONAL)) - { - /* reset node */ - coNmtStateReq(nodeLookupTable_gast[arrIndex_u8].nodeId_u8, CO_NMT_STATE_RESET_NODE, CO_FALSE); - } - } -} - diff --git a/common/nms_types.h b/common/nms_types.h index c798e12..4c3a929 100644 --- a/common/nms_types.h +++ b/common/nms_types.h @@ -76,7 +76,10 @@ typedef enum NMS_ERR_NOT_INITIALIZED, /* The initialization was unsuccessful */ NMS_ERR_NOT_RUNNING, /* Module has not been started */ NMS_ERR_BUS_ERROR, /* Memory cannot be physically addressed (e.g. invalid bus address) */ - NMS_ERR_NULL_POINTER + NMS_ERR_NULL_POINTER, + NMS_ERR_INVALID_MODULE, + NMS_ERR_INVALID_POINTER, + NMS_LSS_NODE_CONFIG_ERROR, } NMSErrorEn; #endif /* NMS_TYPES_H_INCLUDED */