Other Parts Discussed in Thread: LP-AM243
Tool/software:
EDS FILE $ EZ-EDS Version 3.34.1.20231010 Generated Electronic Data Sheet [File] DescText = "EtherNet/IP(tm) Adapter am243x-lp freeRTOS"; CreateDate = 08-19-2021; CreateTime = 17:53:35; ModDate = 02-29-2024; ModTime = 07:00:00; Revision = 3.7; HomeURL = "www.ti.com"; [Device] VendCode = 806; VendName = "Texas Instruments"; ProdType = 43; ProdTypeStr = "Analog I/O + GPIO Adapter"; ; More specific ProdCode = 24311; MajRev = 3; MinRev = 7; ProdName = "LP-AM243 8AI/2DI/2DO Adapter"; ; Much clearer in device list Catalog = "AM243-8AI"; ; Friendly name for inventory lists Icon = "ti.ico"; IconContents = "AAABAAEAICAAAAAAIACsAwAAFgAAAIlQTkcNChoKAAAADUlIRFIAAAAgAAAA" "IAgGAAAAc3p69AAAAAFzUkdCAK7OHOkAAAAEZ0FNQQAAsY8L/GEFAAAACXBI" "WXMAAA7DAAAOwwHHb6hkAAADQUlEQVRYR+1WSS9kURQusyBmNnaGxBghYpbY" "CZGQYIWFhUQQiSkWhKUhVhIr/kzPqqhXhlK6KE2V7pL2J26f77j35T3ea0pK" "rXzJSb07nfOd7557bzk+8Brcra2Jo4ICcVxUpJtG7bOKCiGnvC9up6fFV4dD" "OA32g+woMfEZgfDmpghvbESXWGh+XhwgoMFcZJ6cHFOg4OKi+ET9ICe7ogMr" "AlDBk51tCuRrbRWfqf+4uDhGBHJzoxvIDlYEDvFLNeDv7RV/d3aYyM3EhAiM" "juqkLvv7xdXgoAgMDYmrgQH+lkORwYqAIgHJQwsL7PibbOMbhfiFvr+ToSYw" "hkLGWMSwUwB9KiCAYNgafP/s7mYCrJT8hfHESBGcmzMRUM5OSkuFt6WFnd5M" "TnKWnsxMbl+Pj4vjsjLeJszFqXkzgbuVlcdzLw1ZaunpJmdeupSgwEVbm6lf" "y8ri+SCg1IkYv0ZGdAWQBch46+pMzpApFIBasovhjIvTs8e6G1JGDpmBQWdC" "gnAlJZktJUW44uPZAQjAGeaiquVSBghCgYf9fb3/D13h6DOudSUnWxM4ra7m" "ouFJFqbkhzOYOz9fnNbWsrOHvb3HQJQt2uH1dXFSWSk0uieMa2GY52tutibh" "LizkCcYFdoaMITnWhWZn+RuPFNpn5eWcDPbcat3TOjHBTa+cseDsDM49eXns" "yEcOccZ98kRoGRmWwWEg4O/stCcAqMKxcqAMji7prGO+m94EZBycmuI2ErBb" "/yoC/q4uVkEVDwwOjVlh/PfqKjtCoWLreDHBmZYmXFTQql6MPqCUt6bm/wQA" "OMQCOECwAzhMTdWJ4VdOtcRFRwdni7nwA38wNxXm3dLSywT8PT38tkNaX3u7" "vsDb2MiO4Fx2WcLX1MRzYCDrpbYcej2ux8ZEYHj42UIogaq/3962dapRXUBu" "TRZqVBGcmWECh7TXAbol73d3TUFCy8s8ru6Jd8Eh3Y6QV+0tAqpvbNu7ZG7E" "Lb1+CIbqVtWu7M2PTqRw0gP09MJBwZ3X18eGAP4JQXp16SB7qHLZ1xcbAsBZ" "VRUHVfJDgZgSAM4bGvjIITgUOSkpiS0BILy1JfAK4jGDKrL7Ay/A4fgH+CbX" "ULuRjXIAAAAASUVORK5CYII="; [Device Classification] Class1 = EtherNetIP; [Params] Param1 = 0, $ first field shall equal 0 7,"20 70 24 01 31 08 03", $ path size,path 0x0000, $ descriptor 0xC6, $ data type 1, $ data size in bytes "Output1", $ name "", $ units "Output Byte 1", $ help string ,,0, $ min, max, default data values ,,,, $ mult, dev, base, offset scaling not used ,,,, $ mult, dev, base, offset link not used 0; $ decimal places not used Param2 = 0, $ reserved, shall equal 0 7,"20 70 24 01 31 09 03", $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Output2", $ name "", $ units "Output Byte 2", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param3 = 0, $ reserved, shall equal 0 7,"20 70 24 01 31 0A 03", $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Output3", $ name "", $ units "Output Byte 3", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param4 = 0, $ reserved, shall equal 0 7,"20 70 24 01 31 0B 03", $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Output4", $ name "", $ units "Output Byte 4", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param5 = 0, $ reserved, shall equal 0 7,"20 70 24 01 31 0C 03", $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Output5", $ name "", $ units "Output Byte 5", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param6 = 0, $ reserved, shall equal 0 ,, $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Output6", $ name "", $ units "Parameter 6", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param7 = 0, $ reserved, shall equal 0 ,, $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Output7", $ name "", $ units "Parameter 7", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param8 = 0, $ reserved, shall equal 0 ,, $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Output8", $ name "", $ units "Parameter 8", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param9 = 0, $ reserved, shall equal 0 ,, $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Output9", $ name "", $ units "Parameter 9", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param10 = 0, $ reserved, shall equal 0 ,, $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Output10", $ name "", $ units "Parameter 10", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param11 = 0, $ reserved, shall equal 0 7,"20 70 24 01 31 00 03", $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Input1", $ name "", $ units "Input Byte 1", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param12 = 0, $ reserved, shall equal 0 7,"20 70 24 01 31 01 03", $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Input2", $ name "", $ units "Input Byte 2", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param13 = 0, $ reserved, shall equal 0 7,"20 70 24 01 31 02 03", $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Input3", $ name "", $ units "Input Byte 3", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param14 = 0, $ reserved, shall equal 0 7,"20 70 24 01 31 03 03", $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Input4", $ name "", $ units "Input Byte 4", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param15 = 0, $ reserved, shall equal 0 7,"20 70 24 01 31 04 03", $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Input5", $ name "", $ units "Input Byte 5", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param16 = 0, $ reserved, shall equal 0 ,, $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Input6", $ name "", $ units "Parameter 16", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param17 = 0, $ reserved, shall equal 0 ,, $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Input7", $ name "", $ units "Parameter 17", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param18 = 0, $ reserved, shall equal 0 ,, $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Input8", $ name "", $ units "Parameter 18", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param19 = 0, $ reserved, shall equal 0 ,, $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Input9", $ name "", $ units "Parameter 19", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places Param20 = 0, $ reserved, shall equal 0 ,, $ Link Path Size, Link Path 0x0000, $ Descriptor 0xC6, $ Data Type 1, $ Data Size in bytes "Input10", $ name "", $ units "Parameter 20", $ help string ,,0, $ min, max, default data values ,,,, $ mult, div, base, offset scaling ,,,, $ mult, div, base, offset links ; $ decimal places ; -------- Analog Inputs 0–7 (0x0310–0x0317) -------- Param21 = 0,7,"20 70 24 01 31 10 03", 0x0000, 0xC7, 2, "AI0", "", "Analog Input 0 (0–5V or 4–20mA)", ,,0,,,,,,,; Param22 = 0,7,"20 70 24 01 31 11 03", 0x0000, 0xC7, 2, "AI1", "", "Analog Input 1", ,,0,,,,,,,; Param23 = 0,7,"20 70 24 01 31 12 03", 0x0000, 0xC7, 2, "AI2", "", "Analog Input 2", ,,0,,,,,,,; Param24 = 0,7,"20 70 24 01 31 13 03", 0x0000, 0xC7, 2, "AI3", "", "Analog Input 3", ,,0,,,,,,,; Param25 = 0,7,"20 70 24 01 31 14 03", 0x0000, 0xC7, 2, "AI4", "", "Analog Input 4", ,,0,,,,,,,; Param26 = 0,7,"20 70 24 01 31 15 03", 0x0000, 0xC7, 2, "AI5", "", "Analog Input 5", ,,0,,,,,,,; Param27 = 0,7,"20 70 24 01 31 16 03", 0x0000, 0xC7, 2, "AI6", "", "Analog Input 6", ,,0,,,,,,,; Param28 = 0,7,"20 70 24 01 31 17 03", 0x0000, 0xC7, 2, "AI7", "", "Analog Input 7", ,,0,,,,,,,; ; -------- Analog Outputs 0–7 (0x0320–0x0327) -------- Param29 = 0,7,"20 70 24 01 32 00 03", 0x0000, 0xC1, 1, "AO0", "", "Analog Output 0 (Scaled)", ,,0,,,,,,,; Param30 = 0,7,"20 70 24 01 32 01 03", 0x0000, 0xC1, 1, "AO1", "", "Analog Output 1", ,,0,,,,,,,; Param31 = 0,7,"20 70 24 01 32 02 03", 0x0000, 0xC1, 1, "AO2", "", "Analog Output 2", ,,0,,,,,,,; Param32 = 0,7,"20 70 24 01 32 03 03", 0x0000, 0xC1, 1, "AO3", "", "Analog Output 3", ,,0,,,,,,,; Param33 = 0,7,"20 70 24 01 32 04 03", 0x0000, 0xC1, 1, "AO4", "", "Analog Output 4", ,,0,,,,,,,; Param34 = 0,7,"20 70 24 01 32 05 03", 0x0000, 0xC1, 1, "AO5", "", "Analog Output 5", ,,0,,,,,,,; Param35 = 0,7,"20 70 24 01 32 06 03", 0x0000, 0xC1, 1, "AO6", "", "Analog Output 6", ,,0,,,,,,,; Param36 = 0,7,"20 70 24 01 32 07 03", 0x0000, 0xC1, 1, "AO7", "", "Analog Output 7", ,,0,,,,,,,; ; -------- Digital Inputs (0x0330, 0x0331) -------- Param37 = 0,7,"20 70 24 01 33 00 03", 0x0000, 0xC1, 1, "DI0", "", "Digital Input 0", ,,0,,,,,,,; Param38 = 0,7,"20 70 24 01 33 01 03", 0x0000, 0xC1, 1, "DI1", "", "Digital Input 1", ,,0,,,,,,,; ; -------- Digital Outputs (0x0340, 0x0341) -------- Param39 = 0,7,"20 70 24 01 34 00 03", 0x0000, 0xC1, 1, "DO0", "", "Digital Output 0", ,,0,,,,,,,; Param40 = 0,7,"20 70 24 01 34 01 03", 0x0000, 0xC1, 1, "DO1", "", "Digital Output 1", ,,0,,,,,,,; [Assembly] Object_Name = "Assembly Object"; Object_Class_Code = 0x04; MaxInst = 6; Number_Of_Static_Instances = 6; Max_Number_Of_Dynamic_Instances = 0; Assem1 = "Producing Assembly (Input Data)", , 5, 0x0001, ,, 8,Param11, 8,Param12, 8,Param13, 8,Param14, 8,Param15; Assem2 = "Consuming Assembly (Output Data)", , 5, 0x0001, ,, 8,Param1, 8,Param2, 8,Param3, 8,Param4, 8,Param5; Assem3 = "Analog Inputs 8AI", , 5, 0x0001, ,, 8,Param21, 8,Param22, 8,Param23, 8,Param24, 8,Param25, 8,Param26, 8,Param27, 8,Param28; Assem4 = "Analog Outputs 8AO", , 5, 0x0001, ,, 8,Param29, 8,Param30, 8,Param31, 8,Param32, 8,Param33, 8,Param34, 8,Param35, 8,Param36; Assem5 = "Digital Inputs 2DI", , 1, 0x0065, ,, 1,Param37, 1,Param38; Assem6 = "Digital Outputs 2DO", , 1, 0x0064, ,, 1,Param39, 1,Param40; [Connection Manager] Object_Name = "Connection Manager Object"; Object_Class_Code = 0x06; Connection1 = 0x04010002, $ trigger & transport $ 0-15 = supported transport classes (class 1) $ 16 = cyclic (1 = supported) $ 17 = change of state (0 = not supported) $ 18 = on demand (0 = not supported) $ 19-23 = reserved (must be zero) $ 24-27 = exclusive owner $ 28-30 = reserved (must be zero) $ 31 = client 0 (don't care for classes 0 and 1) 0x44640005, $ point/multicast & priority & realtime format $ 0 = O=>T fixed (1 = supported) $ 1 = O=>T variable (0 = not supported) $ 2 = T=>O fixed (1 = supported) $ 3 = T=>O variable (0 = not supported) $ 4-7 = reserved (must be zero) $ 8-10 = O=>T header (4 byte run/idle) $ 11 = reserved (must be zero) $ 12-14 = T=>O header $ 15 = reserved (must be zero) $ 16-19 = O=>T point-to-point $ 20-23 = T=>O multicast $ 24-27 = O=>T scheduled $ 28-31 = T=>O scheduled ,,Assem2, $ O=>T RPI,Size,Format ,,Assem1, $ T=>O RPI,Size,Format ,, $ config part 1 (dynamic assemblies) ,, $ config part 2 (module configuration) "Exclusive Owner", $ connection name "", $ Help string "20 04 24 01 2C 65 2C 64"; $ exclusive owner path Connection2 = 0x02010002, $ trigger & transport $ 0-15 = supported transport classes (class 1) $ 16 = cyclic (1 = supported) $ 17 = change of state (0 = not supported) $ 18 = on demand (0 = not supported) $ 19-23 = reserved (must be zero) $ 24-27 = exclusive owner $ 28-30 = reserved (must be zero) $ 31 = client 0 (don't care for classes 0 and 1) 0x44640305, $ point/multicast & priority & realtime format $ 0 = O=>T fixed (1 = supported) $ 1 = O=>T variable (0 = not supported) $ 2 = T=>O fixed (1 = supported) $ 3 = T=>O variable (0 = not supported) $ 4-7 = reserved (must be zero) $ 8-10 = O=>T header (4 byte run/idle) $ 11 = reserved (must be zero) $ 12-14 = T=>O header $ 15 = reserved (must be zero) $ 16-19 = O=>T point-to-point $ 20-23 = T=>O multicast $ 24-27 = O=>T scheduled $ 28-31 = T=>O scheduled ,0,, $ O=>T RPI,Size,Format ,,Assem1, $ T=>O RPI,Size,Format ,, $ config part 1 (dynamic assemblies) ,, $ config part 2 (module configuration) "Input Only", $ connection name "", $ Help string "20 04 24 01 2C FE 2C 64"; $ input only path Connection3 = 0x01010002, $ trigger & transport $ 0-15 = supported transport classes (class 1) $ 16 = cyclic (1 = supported) $ 17 = change of state (0 = not supported) $ 18 = on demand (0 = not supported) $ 19-23 = reserved (must be zero) $ 24-27 = exclusive owner $ 28-30 = reserved (must be zero) $ 31 = client 0 (don't care for classes 0 and 1) 0x44640305, $ point/multicast & priority & realtime format $ 0 = O=>T fixed (1 = supported) $ 1 = O=>T variable (0 = not supported) $ 2 = T=>O fixed (1 = supported) $ 3 = T=>O variable (0 = not supported) $ 4-7 = reserved (must be zero) $ 8-10 = O=>T header (4 byte run/idle) $ 11 = reserved (must be zero) $ 12-14 = T=>O header $ 15 = reserved (must be zero) $ 16-19 = O=>T point-to-point $ 20-23 = T=>O multicast $ 24-27 = O=>T scheduled $ 28-31 = T=>O scheduled ,0,, $ O=>T RPI,Size,Format ,,Assem1, $ T=>O RPI,Size,Format ,, $ config part 1 (dynamic assemblies) ,, $ config part 2 (module configuration) "Listen Only", $ connection name "", $ Help string "20 04 24 01 2C FF 2C 64"; $ listen only path Connection4 = 0x04010002, 0x44640005, ,,Assem3, ; T=>O: Analog Inputs (AI0–AI7) ,, ,, "AI Group", "", "20 04 24 03 2C C3 2C C3"; Connection5 = 0x04010002, 0x44640005, ,,Assem4, ; O=>T: Analog Outputs (AO0–AO7) ,, ,, "Analog Outputs (SPI)", "", "20 04 24 04 2C C4 2C C4"; Connection6 = 0x04010002, 0x44640005, ,,Assem5, ; T=>O: Digital Inputs (DI0–DI1) ,, ,, "Digital Inputs", "", "20 04 24 05 2C C5 2C C5"; Connection7 = 0x04010002, 0x44640005, ,,Assem6, ; O=>T: Digital Outputs (DO0–DO1) ,, ,, "Digital Outputs", "", "20 04 24 06 2C C6 2C C6"; [Capacity] MaxCIPConnections = 12; MaxConsumersPerMcast = 3; TSpec1 = TxRx, 5, 500; [DLR Class] Revision = 3; Object_Name = "Device Level Ring Object"; Object_Class_Code = 0x47; MaxInst = 1; Number_Of_Static_Instances = 1; Max_Number_Of_Dynamic_Instances = 0; Ring_Supervisor_Capable = No; [TCP/IP Interface Class] Revision = 4; Object_Name = "TCP/IP Interface Object"; Object_Class_Code = 0xF5; MaxInst = 1; Number_Of_Static_Instances = 1; Max_Number_Of_Dynamic_Instances = 0; ENetQCT1 = $ Numbers are preliminary estimates only: 4000, $ Ready for Connection Time 500; $ Accumulated CIP Connection Time [Ethernet Link Class] Revision = 4; Object_Name = "Ethernet Link Object"; Object_Class_Code = 0xF6; MaxInst = 2; Number_Of_Static_Instances = 2; Max_Number_Of_Dynamic_Instances = 0; InterfaceLabel1 = "Port 1"; InterfaceLabel2 = "Port 2"; [Time Sync Class] Revision = 4; Object_Name = "Time Sync Object"; Object_Class_Code = 0x43; MaxInst = 1; Number_Of_Static_Instances = 1; Max_Number_Of_Dynamic_Instances = 0; [QoS Class] Revision = 1; Object_Name = "QoS Object"; Object_Class_Code = 0x48; MaxInst = 1; Number_Of_Static_Instances = 1; Max_Number_Of_Dynamic_Instances = 0; [LLDP Management Class] Revision = 1; Object_Name = "LLDP Management Object"; Object_Class_Code = 0x109; MaxInst = 1; Number_Of_Static_Instances = 1; Max_Number_Of_Dynamic_Instances = 0; [LLDP Data Table Class] Revision = 1; Object_Name = "LLDP Data Table Object"; Object_Class_Code = 0x10A; MaxInst = 16; Number_Of_Static_Instances = 0; Max_Number_Of_Dynamic_Instances = 16; APPIO.C #include "appIO.h" #include <drivers/gpio.h> #include <drivers/hw_include/hw_types.h> // For HW_WR_REG32 #include <kernel/dpl/DebugP.h> #include "ti_drivers_config.h" // For CONFIG_GPIO_* macros // EtherNet/IP Input Assembly (bit-packed digital inputs) static uint8_t g_input_assembly_101[1] = {0}; // 2 DI bits packed into 1 byte // EtherNet/IP Output Assembly (bit-packed digital outputs) static uint8_t g_output_assembly_100[1] = {0}; // 2 DO bits packed into 1 byte void EI_APP_IO_init(void) { DebugP_log("EI_APP_IO_init: Configuring 2 Digital Inputs and 2 Digital Outputs\n"); // INPUTS configured in SysConfig (set as GPIO_IN with pull-up/down as needed) GPIO_setDirMode(CONFIG_GPIO_INPUT0_BASE_ADDR, CONFIG_GPIO_INPUT0_PIN, GPIO_DIRECTION_INPUT); GPIO_setDirMode(CONFIG_GPIO_INPUT1_BASE_ADDR, CONFIG_GPIO_INPUT1_PIN, GPIO_DIRECTION_INPUT); // OUTPUTS configured in SysConfig (set as GPIO_OUT) GPIO_setDirMode(CONFIG_GPIO_OUTPUT0_BASE_ADDR, CONFIG_GPIO_OUTPUT0_PIN, GPIO_DIRECTION_OUTPUT); GPIO_setDirMode(CONFIG_GPIO_OUTPUT1_BASE_ADDR, CONFIG_GPIO_OUTPUT1_PIN, GPIO_DIRECTION_OUTPUT); // Optional: set initial output states GPIO_pinWriteHigh(CONFIG_GPIO_OUTPUT0_BASE_ADDR, CONFIG_GPIO_OUTPUT0_PIN); GPIO_pinWriteLow(CONFIG_GPIO_OUTPUT1_BASE_ADDR, CONFIG_GPIO_OUTPUT1_PIN); } void EI_APP_IO_cyclic(void) { /* === Read 2 Digital Inputs === */ uint8_t di0 = GPIO_pinRead(CONFIG_GPIO_INPUT0_BASE_ADDR, CONFIG_GPIO_INPUT0_PIN) & 0x01; uint8_t di1 = GPIO_pinRead(CONFIG_GPIO_INPUT1_BASE_ADDR, CONFIG_GPIO_INPUT1_PIN) & 0x01; g_input_assembly_101[0] = (di1 << 1) | di0; // Bit 1 = DI1, Bit 0 = DI0 /* === Apply 2 Digital Outputs === */ /* uint8_t do_bits = g_output_assembly_100[0]; if (do_bits & (1 << 0)) { GPIO_pinWriteHigh(CONFIG_GPIO_OUTPUT0_BASE_ADDR, CONFIG_GPIO_OUTPUT0_PIN); } else { GPIO_pinWriteLow(CONFIG_GPIO_OUTPUT0_BASE_ADDR, CONFIG_GPIO_OUTPUT0_PIN); } if (do_bits & (1 << 1)) { GPIO_pinWriteHigh(CONFIG_GPIO_OUTPUT1_BASE_ADDR, CONFIG_GPIO_OUTPUT1_PIN); } else { GPIO_pinWriteLow(CONFIG_GPIO_OUTPUT1_BASE_ADDR, CONFIG_GPIO_OUTPUT1_PIN); } */ // --- Apply 2 Digital Outputs --- uint8_t do0 = g_output_assembly_100[0] & 0x01; uint8_t do1 = (g_output_assembly_100[0] >> 1) & 0x01; if (do0) GPIO_pinWriteHigh(CONFIG_GPIO_OUTPUT0_BASE_ADDR, CONFIG_GPIO_OUTPUT0_PIN); else GPIO_pinWriteLow(CONFIG_GPIO_OUTPUT0_BASE_ADDR, CONFIG_GPIO_OUTPUT0_PIN); if (do1) GPIO_pinWriteHigh(CONFIG_GPIO_OUTPUT1_BASE_ADDR, CONFIG_GPIO_OUTPUT1_PIN); else GPIO_pinWriteLow(CONFIG_GPIO_OUTPUT1_BASE_ADDR, CONFIG_GPIO_OUTPUT1_PIN); // Debug log AFTER values are computed DebugP_log("DI: %d %d, DO: %d %d\n", di0, di1, do0, do1); } uint8_t *EI_APP_IO_getInputAssembly(void) { return g_input_assembly_101; } uint8_t *EI_APP_IO_getOutputAssembly(void) { return g_output_assembly_100; } APPIO.H #ifndef APP_IO_H_ #define APP_IO_H_ #include <stdint.h> #ifdef __cplusplus extern "C" { #endif void EI_APP_IO_init(void); void EI_APP_IO_cyclic(void); uint8_t *EI_APP_IO_getInputAssembly(void); // Assembly 101 uint8_t *EI_APP_IO_getOutputAssembly(void); // Assembly 100 // add new *** begin #define EI_CLASS_ID_DIGITAL_IO 0xC5 #define EI_INSTANCE_ID_DIGITAL_IO 0x01 //extern uint8_t attr_inputBits; // Mirror of input bit from hardware //extern uint8_t attr_outputBits; // Mirror of output bit from PLC // add new *** end #ifdef __cplusplus } #endif #endif /* APP_IO_H_ */ APP_GENRIC_DEVICE /*! * \file app_generic_device.c * * \brief * Generic device profile declarations. * * \author * Texas Instruments Incorporated * * \copyright * Copyright (C) 2023 Texas Instruments Incorporated * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #if (!(defined FBTLPROVIDER) || (0 == FBTLPROVIDER)) && (!(defined FBTL_REMOTE) || (0 == FBTL_REMOTE)) #include "EI_API_def.h" #include "EI_API.h" //#1a new IO #include "appIO.h" //#1a end IO #include "osal.h" #include "osal_error.h" //#2a new IO #include "EI_API_CIP.h" //#2a end IO #include "drivers/CUST_drivers.h" #include "appLed.h" #include "appNV.h" #include "appCfg.h" #include <device_profiles/app_device_profile.h> #include <device_profiles/app_device_profile_intern.h> #include <device_profiles/generic_device/app_generic_device_cfg.h> #include <device_profiles/generic_device/app_generic_device.h> static uint16_t EI_APP_GENERIC_DEVICE_extendedStatus_s[255] = {0}; static bool EI_APP_GENERIC_DEVICE_init (EI_API_ADP_T *pAdapter, EI_API_CIP_NODE_T *pCipNode); static void EI_APP_GENERIC_DEVICE_run (EI_API_CIP_NODE_T *pCipNode); static bool EI_APP_GENERIC_DEVICE_cipSetup (EI_API_CIP_NODE_T *pCipNode); static void EI_APP_GENERIC_DEVICE_cipGenerateContent (EI_API_CIP_NODE_T *pCipNode, uint16_t classId, uint16_t instanceId); static void EI_APP_DIGITAL_IO_cipGenerateContent(EI_API_CIP_NODE_T* cipNode); /*! * <!-- Description: --> * * \brief * Callback function for ForwardOpen, LargeForwardOpen and ForwardClose. * * \details * Callback function which is called when a request for the services * ForwardOpen, LargeForwardOpen and ForwardClose was received. * */ EI_API_ADP_SEipStatus_t EI_APP_GENERIC_DEVICE_cmgrCb(uint32_t serviceCode, EI_API_ADP_UCmgrInfo_u cmgrInfo) { EI_API_ADP_SEipStatus_t ret_val= {.gen_status=0, .extended_status_size=0, .extended_status_arr=EI_APP_GENERIC_DEVICE_extendedStatus_s}; switch(serviceCode) { case 0x54: // OSAL_printf("Forward open Connection Serial Number: 0x%04x\r\n", cmgrInfo.forwardOpenInfo.conSerialNum); break; case 0x5b: // OSAL_printf("Large forward open Connection Serial Number: 0x%04x\r\n", cmgrInfo.forwardOpenInfo.conSerialNum); break; case 0x4e: // OSAL_printf("Forward close Connection Serial Number: 0x%04x\r\n", cmgrInfo.forwardCloseInfo.conSerialNum); break; default: OSAL_printf("unknown service code %x\r\n", serviceCode); } return ret_val; } /*! * \brief * Registers generic device profile interface functions. * * \details * Called by #EI_APP_DEVICE_PROFILE_init function of device profile interface. * Function needs to be defined in each profile. * * \remark * In time of build process only one device profile can be active. * Rest profiles need to be excluded from the build. * * \param[in] pIntf Pointer to device profile interface which needs to be initialized. * * \return value as bool. * \retval true Success. * \retval false Invalid input parameter defined as NULL. * * \par Example * \code{.c} * #include "device_profiles/generic_device/app_generic_device_cfg.h" * * uint32_t EI_APP_DEVICE_PROFILE_init (void) * { * return EI_APP_DEVICE_PROFILE_register(&EI_APP_DEVICE_PROFILE_intf_s); * } * \endcode * * \see EI_APP_DEVICE_PROFILE_register EI_APP_DEVICE_PROFILE_CFG_init * * \ingroup EI_APP_DEVICE_PROFILE_CFG * */ uint32_t EI_APP_DEVICE_PROFILE_register (EI_APP_DEVICE_PROFILE_Interface_t *pIntf) { uint32_t error = EI_APP_DEVICE_PROFILE_ERR_General; if (NULL == pIntf) { error = EI_APP_DEVICE_PROFILE_ERR_PtrInvalid; goto laError; } pIntf->task.init = EI_APP_GENERIC_DEVICE_init; pIntf->task.run = EI_APP_GENERIC_DEVICE_run; pIntf->cfg.init = EI_APP_GENERIC_DEVICE_CFG_init; pIntf->cfg.isValid = EI_APP_GENERIC_DEVICE_CFG_isValid; pIntf->cfg.setHeader = EI_APP_GENERIC_DEVICE_CFG_setHeader; pIntf->cfg.apply = EI_APP_GENERIC_DEVICE_CFG_apply; pIntf->cfg.setDefaultWithoutComm = EI_APP_GENERIC_DEVICE_CFG_setDefaultWithoutComm; pIntf->cfg.callback = EI_APP_GENERIC_DEVICE_CFG_callback; pIntf->cfg.getRuntimeData = EI_APP_GENERIC_DEVICE_CFG_getRuntimeData; pIntf->cfg.getFactoryResetData = EI_APP_GENERIC_DEVICE_CFG_getFactoryResetData; pIntf->cfg.getLength = EI_APP_GENERIC_DEVICE_CFG_getLength; error = EI_APP_DEVICE_PROFILE_ERR_OK; laError: return error; } /*! * <!-- Description: --> * * \brief * Basic initialization function. * * \details * Creates a new EtherNet/IP™ Adapter.<br> * Initializes data structures from non-volatile storage.<br> * Registers stack error handler.<br> * Initializes the Adapter.<br> * Create a CIP™ node.<br> * */ //#3a begin ***** static uint8_t *pInput = NULL; static uint8_t *pOutput = NULL; static uint8_t attr_inputBits = 0; static uint8_t attr_outputBits = 0; void EI_APP_GENERIC_DEVICE_initPointers(void) { pInput = EI_APP_IO_getInputAssembly(); pOutput = EI_APP_IO_getOutputAssembly(); } //#3a end ****** bool EI_APP_GENERIC_DEVICE_init(EI_API_ADP_T* pAdapter, EI_API_CIP_NODE_T *pCipNode) { bool result = false; #if (defined BRIDGING_AND_ROUTING) && (BRIDGING_AND_ROUTING==1) // Enable Bridging and Routing feature EI_API_ADP_setBridgingAndRoutingSupported(pAdapter); #endif // Create vendor specific classes. result = EI_APP_GENERIC_DEVICE_cipSetup(pCipNode); //##4a BEGIN // ... existing initialization code ... // --- add new *** begin: init pointers and sync attributes --- EI_APP_GENERIC_DEVICE_initPointers(); // Set pInput and pOutput pointers attr_inputBits = pInput[0]; // Sync DI to variable attr_outputBits = pOutput[0]; // Sync DO to variable // --- add new *** end --- //##4a END return result; } /*! * <!-- Description: --> * * \brief * Cyclically called run function. * * \details * Cyclically called run function, handles the EtherNet/IP stack and hardware * specific functionality, such as reading switches, reading inputs, setting outputs * and LEDs. * */ void EI_APP_GENERIC_DEVICE_run(EI_API_CIP_NODE_T* pCipNode) { uint32_t errCode = EI_API_CIP_eERR_OK; uint8_t attrValue = 0; uint16_t attr; // Mirror I/O data for(attr = 0; attr < 5; attr++) { errCode = EI_API_CIP_getAttr_usint(pCipNode, 0x0070, 0x0001, attr + 0x0308, &attrValue); if (attr == 0 && errCode == EI_API_CIP_eERR_OK) { EI_APP_LED_industrialSet(attrValue); } EI_API_CIP_setAttr_usint(pCipNode, 0x0070, 0x0001, attr + 0x0300, attrValue); } //##5a BEGIN APPIO.C --- add new *** begin: Digital IO CIP sync --- extern uint8_t attr_inputBits; extern uint8_t attr_outputBits; uint8_t *pInputAssembly = EI_APP_IO_getInputAssembly(); // Hardware → CIP uint8_t *pOutputAssembly = EI_APP_IO_getOutputAssembly(); // CIP → Hardware // Sync actual input from hardware to CIP input attribute attr_inputBits = pInputAssembly[0]; // Output attribute (set by PLC and mirrored earlier) gets sent to hardware pOutputAssembly[0] = attr_outputBits; //##5a END APPIO.C --- add new *** end --- // Optional future expansion: // EI_APP_CLASS71_run(); } /*! * <!-- Description: --> * * \brief * Setup the application with classes, instances, attributes, and assemblies. * * \details * Setup the application with classes, instances, attributes, and assemblies.<br> * For the assemblies, use instances in the Vendor Specific range of IDs. * */ static bool EI_APP_GENERIC_DEVICE_cipSetup(EI_API_CIP_NODE_T* pCipNode) { uint32_t errCode = 0; uint16_t i = 0; // 1. Create your base class and instance (0x70 / 0x01) uint16_t classId = 0x70; uint16_t instanceId = 0x01; // 2. Register the GENERIC DEVICE class/instance attributes and services EI_APP_GENERIC_DEVICE_cipGenerateContent(pCipNode, classId, instanceId); //#6a add new APPIO.c EI_APP_GENERIC_DEVICE_initPointers(); // Make sure attr_inputBits/outputBits are set first // 3. Create Assembly instances for Output (0x64) and Input (0x65) EI_API_CIP_createAssembly(pCipNode, 0x64, EI_API_CIP_eAR_GET_AND_SET); EI_API_CIP_createAssembly(pCipNode, 0x65, EI_API_CIP_eAR_GET_AND_SET); // 4. Optionally register DIGITAL IO and ANALOG IO class/instances EI_APP_DIGITAL_IO_cipGenerateContent(pCipNode); // EI_APP_ANALOG_IO_cipGenerateContent(pCipNode); // Add attr_outputBits (0x0340) to Output Assembly 0x64 errCode = EI_API_CIP_addAssemblyMember(pCipNode, 0x64, EI_CLASS_ID_DIGITAL_IO, EI_INSTANCE_ID_DIGITAL_IO, 0x02); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to add Digital Output Attribute to Assembly 0x64: 0x%08x\n", errCode); } // Add attr_inputBits (0x0330) to Input Assembly 0x65 errCode = EI_API_CIP_addAssemblyMember(pCipNode, 0x65, EI_CLASS_ID_DIGITAL_IO, EI_INSTANCE_ID_DIGITAL_IO, 0x01); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to add Digital Input Attribute to Assembly 0x65: 0x%08x\n", errCode); } //#6a end APPIO.c #if (defined BRIDGING_AND_ROUTING) && (BRIDGING_AND_ROUTING==1) EI_APP_GENERIC_DEVICE_cipRoutingSampleSetup(pCipNode); EI_APP_GENERIC_DEVICE_cipUnRoutingSampleSetup(pCipNode); #endif errCode = EI_API_CIP_createAssembly(pCipNode, 0xfe, EI_API_CIP_eAR_GET); // Input-only. errCode = EI_API_CIP_createAssembly(pCipNode, 0xff, EI_API_CIP_eAR_GET); // Listen-only. //##1b romoved by Thien called on // errCode = EI_API_CIP_createAssembly(pCipNode, 0x64, EI_API_CIP_eAR_GET_AND_SET); // errCode = EI_API_CIP_createAssembly(pCipNode, 0x65, EI_API_CIP_eAR_GET_AND_SET); //##1b removed end for (i = 0x300; i < 0x305; i++) { errCode = EI_API_CIP_addAssemblyMember(pCipNode, 0x64, classId, instanceId, i); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to add Class ID %#x, Instance ID %#x, Attribute ID %#x to Assembly Instance 0x64: Error code: 0x%08x\n", classId, instanceId, (uint16_t)i, errCode); } errCode = EI_API_CIP_addAssemblyMember(pCipNode, 0x65, classId, instanceId, (uint16_t)(8 + i)); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to add Class ID %#x, Instance ID %#x, Attribute ID %#x to Assembly Instance 0x65: Error code: 0x%08x\n", classId, instanceId, (uint16_t)(8 + i), errCode); } } return true; } /*! * <!-- Description: --> * * \brief * Generates attributes and services for a CIP™class. * * \details * Create a CIP class with a Class IDs using the value specified in parameter classId.<br> * Generates attributes and services for that class.<br> * Adds read and write services.<br> * Adds 64 8-bit attributes with callback function.<br> * Adds 32 16-bit attributes.<br> * Adds 16 32-bit attributes.<br> * Adds 8 64-bit attributes. * */ static void EI_APP_GENERIC_DEVICE_cipGenerateContent(EI_API_CIP_NODE_T* cipNode, uint16_t classId, uint16_t instanceId) { EI_API_CIP_SService_t service; uint64_t i = 0; EI_API_CIP_createClass(cipNode, classId); service.getAttrAllResponseCnt = 0; service.callback = NULL; service.code = EI_API_CIP_eSC_GETATTRSINGLE; EI_API_CIP_addClassService(cipNode, classId, &service); service.code = EI_API_CIP_eSC_SETATTRSINGLE; EI_API_CIP_addClassService(cipNode, classId, &service); EI_API_CIP_createInstance(cipNode, classId, instanceId); service.code = EI_API_CIP_eSC_GETATTRSINGLE; EI_API_CIP_addInstanceService(cipNode, classId, instanceId, &service); service.code = EI_API_CIP_eSC_SETATTRSINGLE; EI_API_CIP_addInstanceService(cipNode, classId, instanceId, &service); uint16_t attribID = 0x300; // 64 USINT (uint8_t). for (i = 0; i < 64; i++) { EI_API_CIP_SAttr_t attr; OSAL_MEMORY_memset(&attr, 0, sizeof(attr)); attr.id = attribID; attr.edt = EI_API_CIP_eEDT_USINT; attr.accessRule = EI_API_CIP_eAR_GET_AND_SET; attr.pvValue = &i; EI_API_CIP_addInstanceAttr(cipNode, classId, instanceId, &attr); EI_API_CIP_setInstanceAttr(cipNode, classId, instanceId, &attr); attribID++; } // 32 UINT (uint16_t). for (i = 0; i < 32; i++) { EI_API_CIP_SAttr_t attr; OSAL_MEMORY_memset(&attr, 0, sizeof(attr)); attr.id = attribID; attr.edt = EI_API_CIP_eEDT_UINT; attr.accessRule = EI_API_CIP_eAR_GET_AND_SET; attr.pvValue = &i; EI_API_CIP_addInstanceAttr(cipNode, classId, instanceId, &attr); EI_API_CIP_setInstanceAttr(cipNode, classId, instanceId, &attr); attribID++; } // 16 UDINT (uint32_t). for (i = 0; i < 16; i++) { EI_API_CIP_SAttr_t attr; OSAL_MEMORY_memset(&attr, 0, sizeof(attr)); attr.id = attribID; attr.edt = EI_API_CIP_eEDT_UDINT; attr.accessRule = EI_API_CIP_eAR_GET_AND_SET; attr.pvValue = &i; EI_API_CIP_addInstanceAttr(cipNode, classId, instanceId, &attr); EI_API_CIP_setInstanceAttr(cipNode, classId, instanceId, &attr); attribID++; } // 8 ULINT (uint64_t). for (i = 0; i < 8; i++) { EI_API_CIP_SAttr_t attr; OSAL_MEMORY_memset(&attr, 0, sizeof(attr)); attr.id = attribID; attr.edt = EI_API_CIP_eEDT_ULINT; attr.accessRule = EI_API_CIP_eAR_GET_AND_SET; attr.pvValue = &i; EI_API_CIP_addInstanceAttr(cipNode, classId, instanceId, &attr); EI_API_CIP_setInstanceAttr(cipNode, classId, instanceId, &attr); attribID++; } } //#7a ADD BEGIN APPIO.C CLASS ******** //#define EI_CLASS_ID_DIGITAL_IO 0x0066 //#define EI_INSTANCE_ID_DIGITAL_IO 0x0001 // Declare global digital I/O variables bool di0 = false; bool di1 = false; bool do0 = false; bool do1 = false; static void EI_APP_DIGITAL_IO_cipGenerateContent(EI_API_CIP_NODE_T* cipNode) { EI_API_CIP_SService_t service; EI_API_CIP_SAttr_t attr; // 1. Create Class 0x66 EI_API_CIP_createClass(cipNode, EI_CLASS_ID_DIGITAL_IO); // 2. Add Class Services service.getAttrAllResponseCnt = 0; service.callback = NULL; service.code = EI_API_CIP_eSC_GETATTRSINGLE; EI_API_CIP_addClassService(cipNode, EI_CLASS_ID_DIGITAL_IO, &service); service.code = EI_API_CIP_eSC_SETATTRSINGLE; EI_API_CIP_addClassService(cipNode, EI_CLASS_ID_DIGITAL_IO, &service); // 3. Create Instance EI_API_CIP_createInstance(cipNode, EI_CLASS_ID_DIGITAL_IO, EI_INSTANCE_ID_DIGITAL_IO); // 4. Add Instance Services service.code = EI_API_CIP_eSC_GETATTRSINGLE; EI_API_CIP_addInstanceService(cipNode, EI_CLASS_ID_DIGITAL_IO, EI_INSTANCE_ID_DIGITAL_IO, &service); service.code = EI_API_CIP_eSC_SETATTRSINGLE; EI_API_CIP_addInstanceService(cipNode, EI_CLASS_ID_DIGITAL_IO, EI_INSTANCE_ID_DIGITAL_IO, &service); // 5. Attribute 0x0330 → DI0 (Read-only) OSAL_MEMORY_memset(&attr, 0, sizeof(attr)); attr.id = 0x0330; attr.edt = EI_API_CIP_eEDT_BOOL; attr.accessRule = EI_API_CIP_eAR_GET; attr.pvValue = &di0; EI_API_CIP_addInstanceAttr(cipNode, EI_CLASS_ID_DIGITAL_IO, EI_INSTANCE_ID_DIGITAL_IO, &attr); // 6. Attribute 0x0331 → DI1 (Read-only) OSAL_MEMORY_memset(&attr, 0, sizeof(attr)); attr.id = 0x0331; attr.edt = EI_API_CIP_eEDT_BOOL; attr.accessRule = EI_API_CIP_eAR_GET; attr.pvValue = &di1; EI_API_CIP_addInstanceAttr(cipNode, EI_CLASS_ID_DIGITAL_IO, EI_INSTANCE_ID_DIGITAL_IO, &attr); // 7. Attribute 0x0340 → DO0 (Read/Write) OSAL_MEMORY_memset(&attr, 0, sizeof(attr)); attr.id = 0x0340; attr.edt = EI_API_CIP_eEDT_BOOL; attr.accessRule = EI_API_CIP_eAR_GET_AND_SET; attr.pvValue = &do0; EI_API_CIP_addInstanceAttr(cipNode, EI_CLASS_ID_DIGITAL_IO, EI_INSTANCE_ID_DIGITAL_IO, &attr); // 8. Attribute 0x0341 → DO1 (Read/Write) OSAL_MEMORY_memset(&attr, 0, sizeof(attr)); attr.id = 0x0341; attr.edt = EI_API_CIP_eEDT_BOOL; attr.accessRule = EI_API_CIP_eAR_GET_AND_SET; attr.pvValue = &do1; EI_API_CIP_addInstanceAttr(cipNode, EI_CLASS_ID_DIGITAL_IO, EI_INSTANCE_ID_DIGITAL_IO, &attr); } //##7a ADD END APPIO.C CLASS ************** #if (defined BRIDGING_AND_ROUTING) && (BRIDGING_AND_ROUTING==1) /*! * <!-- Description: --> * * \brief * Callback function is triggered when get_attribute_service request is received during explicit messaging. * This function must be shown to the attribute get_callback during setup. * * \details * * */ uint32_t EI_APP_GENERIC_DEVICE_CLASS70_GetAttr2Inst1_Link1_cb (EI_API_CIP_NODE_T *pCipNode, uint16_t classId, uint16_t instanceId, uint16_t attrId, uint16_t *pLen, void *pvValue, uint16_t linkAddress) { /*USINT val*/ *pLen = sizeof(uint8_t); //value to be returned as get attr response *(uint8_t*)pvValue = 13; return EI_API_eERR_CB_NO_ERROR; } /*! * <!-- Description: --> * * \brief * Callback function is triggered when set_attribute_service request is received during explicit messaging. * This function must be shown to the attribute set_callback during setup. * * \details * * */ uint32_t EI_APP_GENERIC_DEVICE_CLASS70_SetAttr2Inst1_Link1_cb (EI_API_CIP_NODE_T *pCipNode, uint16_t classId, uint16_t instanceId, uint16_t attrId, uint16_t len, void *pvValue, uint16_t linkAddress) { uint8_t data=*((uint8_t*)pvValue); OSALUNREF_PARM(data); return EI_API_eERR_CB_NO_ERROR; } /*! * <!-- Description: --> * * \brief * Callback function is triggered when get_attribute_service request is received during explicit messaging. * This function must be shown to the attribute get_callback during setup. * * \details * * */ uint32_t EI_APP_GENERIC_DEVICE_CLASS70_GetAttr2Inst1_cb (EI_API_CIP_NODE_T *pCipNode, uint16_t classId, uint16_t instanceId, uint16_t attrId, uint16_t *pLen, void *pvValue) { /*USINT val*/ *pLen = sizeof(uint8_t); //value to be returned as get attr response *(uint8_t*)pvValue = 13; return EI_API_eERR_CB_NO_ERROR; } /*! * <!-- Description: --> * * \brief * Callback function is triggered when set_attribute_service request is received during explicit messaging. * This function must be shown to the attribute set_callback during setup. * * \details * * */ uint32_t EI_APP_GENERIC_DEVICE_CLASS70_SetAttr2Inst1_cb (EI_API_CIP_NODE_T *pCipNode, uint16_t classId, uint16_t instanceId, uint16_t attrId, uint16_t len, void *pvValue) { uint8_t data=*((uint8_t*)pvValue); OSALUNREF_PARM(data); return EI_API_eERR_CB_NO_ERROR; } /*! * <!-- Description: --> * * \brief * In order to observe configurationAssemblies data , EI_APP_CFGASSEM_cb was created. * * \details * * */ uint32_t EI_APP_GENERIC_DEVICE_CFGASSEM_cb (EI_API_CIP_NODE_T *pCipNode, uint16_t o2t, uint16_t t2o, uint16_t cfg_inst, const uint8_t* const pCfgData, uint16_t cfgDataSize, uint16_t linkaddr) { return EI_API_eERR_CB_NO_ERROR; } /*! * <!-- Description: --> * * \brief * Call EI_APP_cipGenerateContentCipRouting function in order to create Assembly and use routable functionality. * * \details * A routableInstance has been created by cipGenerateContent. Assemblies attributes are setting in this function. */ void EI_APP_GENERIC_DEVICE_cipGenerateContentCipRouting (EI_API_CIP_NODE_T *pCipNode, uint16_t classId, uint16_t instanceId, uint8_t linkAddr) { EI_API_CIP_SService_t service; uint16_t i = 0; uint16_t attribID = 0x300; uint32_t errCode = 0; errCode = EI_API_CIP_createRoutableInstance(pCipNode, classId, instanceId, linkAddr); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to create routable instance\n"); } service.getAttrAllResponseCnt = 0; service.callback = NULL; service.code = EI_API_CIP_eSC_GETATTRSINGLE; errCode = EI_API_CIP_addRoutableInstanceService(pCipNode, classId, instanceId, &service, linkAddr); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to add routable instance service\n"); } service.code = EI_API_CIP_eSC_SETATTRSINGLE; errCode = EI_API_CIP_addRoutableInstanceService(pCipNode, classId, instanceId, &service, linkAddr); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to add routable instance service\n"); } // 64 USINT (uint8_t). for (i = 0; i < 64; i++) { EI_API_CIP_SAttr_t attr; memset(&attr, 0, sizeof(attr)); attr.id = attribID; attr.edt = EI_API_CIP_eEDT_USINT; attr.accessRule = EI_API_CIP_eAR_GET_AND_SET; attr.pvValue = &i; errCode = EI_API_CIP_addRoutableInstanceAttr(pCipNode, classId, instanceId, &attr, linkAddr); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to add routable instance service\n"); } // errCode = EI_API_CIP_setRoutableInstanceAttrFunc(pCipNode, classId, instanceId, &attr, linkAddr); // // if (errCode != EI_API_CIP_eERR_OK) // { // OSAL_printf("Failed to set routable instance service\n"); // } attribID++; } // 32 UINT (uint16_t). for (i = 0; i < 32; i++) { EI_API_CIP_SAttr_t attr; memset(&attr, 0, sizeof(attr)); attr.id = attribID; attr.edt = EI_API_CIP_eEDT_UINT; attr.accessRule = EI_API_CIP_eAR_GET_AND_SET; attr.pvValue = &i; EI_API_CIP_addRoutableInstanceAttr(pCipNode, classId, instanceId, &attr, linkAddr); // EI_API_CIP_setRoutableInstanceAttrFunc(cipNode_s, classId, instanceId, &attr, linkAddr); attribID++; } // 16 UDINT (uint32_t). for (i = 0; i < 16; i++) { EI_API_CIP_SAttr_t attr; memset(&attr, 0, sizeof(attr)); attr.id = attribID; attr.edt = EI_API_CIP_eEDT_UDINT; attr.accessRule = EI_API_CIP_eAR_GET_AND_SET; attr.pvValue = &i; EI_API_CIP_addRoutableInstanceAttr(pCipNode, classId, instanceId, &attr, linkAddr); // EI_API_CIP_setRoutableInstanceAttrFunc(cipNode_s, classId, instanceId, &attr, linkAddr); attribID++; } // 8 ULINT (uint64_t). for (i = 0; i < 8; i++) { EI_API_CIP_SAttr_t attr; memset(&attr, 0, sizeof(attr)); attr.id = attribID; attr.edt = EI_API_CIP_eEDT_ULINT; attr.accessRule = EI_API_CIP_eAR_GET_AND_SET; attr.pvValue = &i; EI_API_CIP_addRoutableInstanceAttr(pCipNode, classId, instanceId, &attr, linkAddr); // EI_API_CIP_setRoutableInstanceAttrFunc(cipNode_s, classId, instanceId, &attr, linkAddr); attribID++; } } /*! * <!-- Description: --> * * \brief * Initialize the application with instance's, attribute's, service's to be able provide unrouting functionality. * This example shows how to set explicit messaging us. * * \details * In the SampleSetup application with instances,attributes callback. * In EI_APP_cipUnRoutingSampleSetup, we must first create an Instance and the Instance services we need. * If you need to Class Instace, You should call EI_API_CIP_addClassAttr() and EI_API_CIP_setClassAttrFunc() as well. */ static bool EI_APP_GENERIC_DEVICE_cipUnRoutingSampleSetup (EI_API_CIP_NODE_T *pCipNode) { uint32_t errCode = 0; uint16_t classId = 0x70; uint16_t instanceId = 6; EI_API_CIP_SAttr_t attr = {0}; const uint16_t attr2_val = 2; EI_API_CIP_SService_t service = {0}; /*creating routable instance 1 which is connected to link addr 1 in the 0x70 class*/ errCode = EI_API_CIP_createInstance(pCipNode, classId, instanceId); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to create Routable Instance\n"); } // set class instance service.code = EI_API_CIP_eSC_GETATTRSINGLE; errCode = EI_API_CIP_addInstanceService(pCipNode, classId, instanceId, &service); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to create Routable Instance\n"); } service.code = EI_API_CIP_eSC_SETATTRSINGLE; errCode = EI_API_CIP_addInstanceService(pCipNode, classId, instanceId, &service); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to create Routable Instance\n"); } attr.id = 2; attr.edt = EI_API_CIP_eEDT_USINT; attr.accessRule = EI_API_CIP_eAR_GET_AND_SET; attr.get_callback = EI_APP_GENERIC_DEVICE_CLASS70_GetAttr2Inst1_cb; attr.set_callback = EI_APP_GENERIC_DEVICE_CLASS70_SetAttr2Inst1_cb; attr.pvValue = (void *)&attr2_val; errCode = EI_API_CIP_addInstanceAttr(pCipNode, classId, instanceId, &attr); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to add Routable Instance Attr\n"); } errCode = EI_API_CIP_setInstanceAttrFunc(pCipNode, classId, instanceId, &attr); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to set Routable Instance attr func\n"); } //Adding class attribute and function EI_API_CIP_addClassAttr (pCipNode, classId, &attr); EI_API_CIP_setClassAttrFunc (pCipNode, classId, &attr); return true; } /*! * <!-- Description: --> * * \brief * Setup the application with routableinstances, routable attributes callback and routableassemblies.. * * \details * In the SampleSetup application with routableinstances, routable attributes callback, and routableassemblies. * In the EI_APP_cipRoutingSampleSetup, first of all,setroutinglinkadress function should be called. after setting routable ports. * routable Instance or assembly Instance can be created. Don't forget it, Rotable side is using the routable callback function no longer. */ static bool EI_APP_GENERIC_DEVICE_cipRoutingSampleSetup (EI_API_CIP_NODE_T *pCipNode) { uint32_t errCode = 0; uint16_t classId = 0x10D; uint16_t instanceId = 1; uint8_t linkAddress = 2; EI_API_CIP_SAttr_t attr = {0}; const uint16_t attr2_val = 2; EI_API_CIP_SService_t service = {0}; const uint8_t maxlinkaddr = 8; uint8_t linkaddr = 0; //Cip routing functions errCode = EI_API_CIP_setRoutingMaxLinkAddr(pCipNode, maxlinkaddr); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to set Max link addr\n"); } errCode= EI_API_CIP_getRoutingMaxLinkAddr(pCipNode, &linkaddr); if ((errCode != EI_API_CIP_eERR_OK) || (linkaddr!= maxlinkaddr)) { OSAL_printf("Failed to get Max link addr\n"); } const uint8_t routablePorts[] = { 11,7,3 }; errCode = EI_API_CIP_setRoutingRoutablePorts(pCipNode, routablePorts, sizeof(routablePorts)/sizeof(uint8_t)); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to set Routable Ports\n"); } // Create instance of 0x70 CIP Routing Cylic IO messaging. EI_APP_GENERIC_DEVICE_cipGenerateContentCipRouting(pCipNode, classId, instanceId, linkAddress); errCode = EI_API_CIP_createCfgAssembly(pCipNode);//CFG ASSEMBLY errCode = EI_API_CIP_createRoutingAssembly(pCipNode, 0xfe, EI_API_CIP_eAR_GET, linkAddress, EI_API_CIP_eAPP_TYPE_IO); // Input-only. (O2T) errCode = EI_API_CIP_createRoutingAssembly(pCipNode, 0xff, EI_API_CIP_eAR_GET, linkAddress, EI_API_CIP_eAPP_TYPE_LO); // Listen-only. errCode = EI_API_CIP_createRoutingAssembly(pCipNode, 3, EI_API_CIP_eAR_GET_AND_SET, linkAddress, EI_API_CIP_eAPP_TYPE_EO);//T2O errCode = EI_API_CIP_createRoutingAssembly(pCipNode, 1, EI_API_CIP_eAR_GET_AND_SET, linkAddress, EI_API_CIP_eAPP_TYPE_EO);//O2T for (uint16_t i = 0x300; i < 0x305; i++) { errCode = EI_API_CIP_addRoutingAssemblyMember(pCipNode, 3, classId, instanceId, i, linkAddress); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to add Class ID %#x, Instance ID %#x, Attribute ID %#x to Assembly Instance 0x64: Error code: 0x%08x\n", classId, instanceId, (uint16_t)i, errCode); } errCode = EI_API_CIP_addRoutingAssemblyMember(pCipNode, 1, classId, instanceId, (uint16_t)(8 + i), linkAddress); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to add Class ID %#x, Instance ID %#x, Attribute ID %#x to Assembly Instance 0x65: Error code: 0x%08x\n", classId, instanceId, (uint16_t)(8 + i), errCode); } } instanceId = 6; /*creating routable instance 1 which is connected to link addr 1 in the 0x70 class*/ errCode = EI_API_CIP_createRoutableInstance(pCipNode, classId, instanceId, linkAddress); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to create Routable Instance\n"); } // set class instance service.code = EI_API_CIP_eSC_GETATTRSINGLE; errCode = EI_API_CIP_addRoutableInstanceService(pCipNode, classId, instanceId, &service, linkAddress); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to create Routable Instance\n"); } service.code = EI_API_CIP_eSC_SETATTRSINGLE; errCode = EI_API_CIP_addRoutableInstanceService(pCipNode, classId, instanceId, &service, linkAddress); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to create Routable Instance\n"); } attr.id = 2; attr.edt = EI_API_CIP_eEDT_USINT; attr.accessRule = EI_API_CIP_eAR_GET_AND_SET; attr.get_callback_routed = EI_APP_GENERIC_DEVICE_CLASS70_GetAttr2Inst1_Link1_cb; attr.set_callback_routed = EI_APP_GENERIC_DEVICE_CLASS70_SetAttr2Inst1_Link1_cb; attr.pvValue = (void *)&attr2_val; errCode = EI_API_CIP_addRoutableInstanceAttr(pCipNode, classId, instanceId, &attr, linkAddress); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to add Routable Instance Attr\n"); } errCode = EI_API_CIP_setRoutableInstanceAttrFunc(pCipNode, classId, instanceId, &attr, linkAddress); if (errCode != EI_API_CIP_eERR_OK) { OSAL_printf("Failed to set Routable Instance attr func\n"); } //Adding class attribute and function EI_API_CIP_addClassAttr (pCipNode, classId, &attr); EI_API_CIP_setClassAttrFunc (pCipNode, classId, &attr); return true; } #endif // (defined BRIDGING_AND_ROUTING) && (BRIDGING_AND_ROUTING==1) #endif // (!(defined FBTLPROVIDER) || (0 == FBTLPROVIDER)) && (!(defined FBTL_REMOTE) || (0 == FBTL_REMOTE)) //*************************************************************************************************