sampleapp_common.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235
  1. /*********************************************************************
  2. * _ _ _
  3. * _ __ | |_ _ | | __ _ | |__ ___
  4. * | '__|| __|(_)| | / _` || '_ \ / __|
  5. * | | | |_ _ | || (_| || |_) |\__ \
  6. * |_| \__|(_)|_| \__,_||_.__/ |___/
  7. *
  8. * www.rt-labs.com
  9. * Copyright 2021 rt-labs AB, Sweden.
  10. *
  11. * This software is dual-licensed under GPLv3 and a commercial
  12. * license. See the file LICENSE.md distributed with this software for
  13. * full license information.
  14. ********************************************************************/
  15. #include "sampleapp_common.h"
  16. #include "app_utils.h"
  17. #include "app_gsdml.h"
  18. #include "app_data.h"
  19. #include "app_log.h"
  20. #include "osal.h"
  21. #include "pnal.h"
  22. #include <pnet_api.h>
  23. #include "pnet_lan9662_api.h"
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. /* Events handled by main task */
  28. #define APP_EVENT_READY_FOR_DATA BIT (0)
  29. #define APP_EVENT_TIMER BIT (1)
  30. #define APP_EVENT_ALARM BIT (2)
  31. #define APP_EVENT_ABORT BIT (15)
  32. /* Defines used for alarm demo functionality */
  33. #define CHANNEL_ERRORTYPE_SHORT_CIRCUIT 0x0001
  34. #define CHANNEL_ERRORTYPE_LINE_BREAK 0x0006
  35. #define CHANNEL_ERRORTYPE_DATA_TRANSMISSION_IMPOSSIBLE 0x8000
  36. #define CHANNEL_ERRORTYPE_NETWORK_COMPONENT_FUNCTION_MISMATCH 0x8008
  37. #define EXTENDED_CHANNEL_ERRORTYPE_FRAME_DROPPED 0x8000
  38. #define EXTENDED_CHANNEL_ERRORTYPE_MAUTYPE_MISMATCH 0x8001
  39. #define EXTENDED_CHANNEL_ERRORTYPE_LINE_DELAY_MISMATCH 0x8002
  40. #define APP_ALARM_USI 0x0010
  41. #define APP_DIAG_CHANNEL_NUMBER 4
  42. #define APP_DIAG_CHANNEL_DIRECTION PNET_DIAG_CH_PROP_DIR_INPUT
  43. #define APP_DIAG_CHANNEL_NUMBER_OF_BITS PNET_DIAG_CH_PROP_TYPE_1_BIT
  44. #define APP_DIAG_CHANNEL_SEVERITY PNET_DIAG_CH_PROP_MAINT_FAULT
  45. #define APP_DIAG_CHANNEL_ERRORTYPE CHANNEL_ERRORTYPE_SHORT_CIRCUIT
  46. #define APP_DIAG_CHANNEL_ADDVALUE_A 0
  47. #define APP_DIAG_CHANNEL_ADDVALUE_B 1234
  48. #define APP_DIAG_CHANNEL_EXTENDED_ERRORTYPE 0
  49. #define APP_DIAG_CHANNEL_QUAL_SEVERITY 0 /* Not used (Max one bit set) */
  50. typedef struct app_data_t
  51. {
  52. pnet_t * net;
  53. /* P-Net configuration passed in app_init(). */
  54. pnet_cfg_t * pnet_cfg;
  55. /* Application api for administration of plugged
  56. *(sub)modules and connection state.
  57. */
  58. app_api_t main_api;
  59. os_timer_t * main_timer;
  60. os_event_t * main_events;
  61. bool alarm_allowed;
  62. pnet_alarm_argument_t alarm_arg;
  63. uint8_t alarm_payload[APP_GSDML_ALARM_PAYLOAD_SIZE];
  64. uint32_t arep_for_appl_ready;
  65. uint32_t appl_ready_delay_count;
  66. bool appl_ready_wait;
  67. uint32_t process_data_tick_counter;
  68. app_mode_t mode;
  69. } app_data_t;
  70. static void app_plug_dap (app_data_t * app, uint16_t number_of_ports);
  71. static int app_set_initial_data_and_ioxs (app_data_t * app);
  72. static void app_cyclic_data_callback (app_subslot_t * subslot, void * tag);
  73. app_data_t app_state;
  74. pnet_t * app_get_pnet_instance (app_data_t * app)
  75. {
  76. if (app != NULL)
  77. {
  78. return app->net;
  79. }
  80. return NULL;
  81. }
  82. app_data_t * app_init (pnet_cfg_t * pnet_cfg, const app_args_t * app_args)
  83. {
  84. app_data_t * app = &app_state;
  85. app->alarm_allowed = true;
  86. app->main_api.arep = UINT32_MAX;
  87. app->pnet_cfg = pnet_cfg;
  88. #if PNET_OPTION_DRIVER_LAN9662
  89. app->mode = app_args->mode;
  90. switch (app->mode)
  91. {
  92. case MODE_HW_OFFLOAD_CPU:
  93. APP_LOG_INFO ("Application RTE mode \"cpu\"\n");
  94. pnet_cfg->driver_enable = true;
  95. break;
  96. case MODE_HW_OFFLOAD_FULL:
  97. APP_LOG_INFO ("Application RTE mode \"full\"\n");
  98. pnet_cfg->driver_enable = true;
  99. break;
  100. case MODE_HW_OFFLOAD_NONE:
  101. APP_LOG_INFO ("Application RTE mode \"none\"\n");
  102. pnet_cfg->driver_enable = false;
  103. break;
  104. default:
  105. APP_LOG_ERROR ("Application mode undefined\n");
  106. pnet_cfg->driver_enable = false;
  107. break;
  108. }
  109. #else
  110. app->mode = MODE_HW_OFFLOAD_NONE;
  111. #endif
  112. app_data_init (app->mode);
  113. app->net = pnet_init (app->pnet_cfg);
  114. if (app->net == NULL)
  115. {
  116. return NULL;
  117. }
  118. return app;
  119. }
  120. static void main_timer_tick (os_timer_t * timer, void * arg)
  121. {
  122. app_data_t * app = (app_data_t *)arg;
  123. os_event_set (app->main_events, APP_EVENT_TIMER);
  124. }
  125. int app_start (app_data_t * app, app_run_in_separate_task_t task_config)
  126. {
  127. if (app == NULL)
  128. {
  129. return -1;
  130. }
  131. app->main_events = os_event_create();
  132. if (app->main_events == NULL)
  133. {
  134. return -1;
  135. }
  136. app->main_timer = os_timer_create (
  137. APP_TICK_INTERVAL_US,
  138. main_timer_tick,
  139. (void *)app,
  140. false);
  141. if (app->main_timer == NULL)
  142. {
  143. os_event_destroy (app->main_events);
  144. return -1;
  145. }
  146. if (task_config == RUN_IN_SEPARATE_THREAD)
  147. {
  148. os_thread_create (
  149. "p-net_sample_app",
  150. APP_MAIN_THREAD_PRIORITY,
  151. APP_MAIN_THREAD_STACKSIZE,
  152. app_loop_forever,
  153. (void *)app);
  154. }
  155. os_timer_start (app->main_timer);
  156. return 0;
  157. }
  158. static void app_set_outputs_default_value (void)
  159. {
  160. // APP_LOG_DEBUG ("Setting outputs to default values.\n");
  161. app_data_set_default_outputs();
  162. }
  163. /*********************************** Callbacks ********************************/
  164. static int app_connect_ind (
  165. pnet_t * net,
  166. void * arg,
  167. uint32_t arep,
  168. pnet_result_t * p_result)
  169. {
  170. APP_LOG_DEBUG ("PLC connect indication. AREP: %u\n", arep);
  171. /*
  172. * Handle the request on an application level.
  173. * This is a very simple application which does not need to handle anything.
  174. * All the needed information is in the AR data structure.
  175. */
  176. return 0;
  177. }
  178. static int app_release_ind (
  179. pnet_t * net,
  180. void * arg,
  181. uint32_t arep,
  182. pnet_result_t * p_result)
  183. {
  184. APP_LOG_DEBUG ("PLC release (disconnect) indication. AREP: %u\n", arep);
  185. app_set_outputs_default_value();
  186. return 0;
  187. }
  188. static int app_dcontrol_ind (
  189. pnet_t * net,
  190. void * arg,
  191. uint32_t arep,
  192. pnet_control_command_t control_command,
  193. pnet_result_t * p_result)
  194. {
  195. APP_LOG_DEBUG (
  196. "PLC dcontrol message. AREP: %u Command: %s\n",
  197. arep,
  198. app_utils_dcontrol_cmd_to_string (control_command));
  199. return 0;
  200. }
  201. static int app_ccontrol_cnf (
  202. pnet_t * net,
  203. void * arg,
  204. uint32_t arep,
  205. pnet_result_t * p_result)
  206. {
  207. APP_LOG_DEBUG (
  208. "PLC ccontrol message confirmation. AREP: %u Status codes: %d "
  209. "%d %d %d\n",
  210. arep,
  211. p_result->pnio_status.error_code,
  212. p_result->pnio_status.error_decode,
  213. p_result->pnio_status.error_code_1,
  214. p_result->pnio_status.error_code_2);
  215. return 0;
  216. }
  217. static int app_write_ind (
  218. pnet_t * net,
  219. void * arg,
  220. uint32_t arep,
  221. uint32_t api,
  222. uint16_t slot_nbr,
  223. uint16_t subslot_nbr,
  224. uint16_t idx,
  225. uint16_t sequence_number,
  226. uint16_t write_length,
  227. const uint8_t * p_write_data,
  228. pnet_result_t * p_result)
  229. {
  230. APP_LOG_DEBUG (
  231. "PLC write record indication.\n"
  232. " AREP: %u API: %u Slot: %2u Subslot: %u Index: %u Sequence: %2u "
  233. "Length: %u\n",
  234. arep,
  235. api,
  236. slot_nbr,
  237. subslot_nbr,
  238. (unsigned)idx,
  239. sequence_number,
  240. write_length);
  241. return 0;
  242. }
  243. static int app_read_ind (
  244. pnet_t * net,
  245. void * arg,
  246. uint32_t arep,
  247. uint32_t api,
  248. uint16_t slot_nbr,
  249. uint16_t subslot_nbr,
  250. uint16_t idx,
  251. uint16_t sequence_number,
  252. uint8_t ** pp_read_data,
  253. uint16_t * p_read_length,
  254. pnet_result_t * p_result)
  255. {
  256. APP_LOG_DEBUG (
  257. "PLC read record indication.\n"
  258. " AREP: %u API: %u Slot: %2u Subslot: %u Index: %u Sequence: %2u Max "
  259. "length: %u\n",
  260. arep,
  261. api,
  262. slot_nbr,
  263. subslot_nbr,
  264. (unsigned)idx,
  265. sequence_number,
  266. (unsigned)*p_read_length);
  267. return 0;
  268. }
  269. static int app_state_ind (
  270. pnet_t * net,
  271. void * arg,
  272. uint32_t arep,
  273. pnet_event_values_t state)
  274. {
  275. uint16_t err_cls = 0; /* Error code 1 */
  276. uint16_t err_code = 0; /* Error code 2 */
  277. const char * error_class_description = "";
  278. const char * error_code_description = "";
  279. app_data_t * app = (app_data_t *)arg;
  280. APP_LOG_DEBUG (
  281. "Event indication %s AREP: %u\n",
  282. app_utils_event_to_string (state),
  283. arep);
  284. if (state == PNET_EVENT_ABORT)
  285. {
  286. if (pnet_get_ar_error_codes (net, arep, &err_cls, &err_code) == 0)
  287. {
  288. app_utils_get_error_code_strings (
  289. err_cls,
  290. err_code,
  291. &error_class_description,
  292. &error_code_description);
  293. APP_LOG_DEBUG (
  294. " Error class: 0x%02x %s \n"
  295. " Error code: 0x%02x %s \n",
  296. (unsigned)err_cls,
  297. error_class_description,
  298. (unsigned)err_code,
  299. error_code_description);
  300. }
  301. else
  302. {
  303. APP_LOG_DEBUG (" No error status available\n");
  304. }
  305. /* Set output values */
  306. app_set_outputs_default_value();
  307. /* Only abort AR with correct session key */
  308. os_event_set (app->main_events, APP_EVENT_ABORT);
  309. }
  310. else if (state == PNET_EVENT_PRMEND)
  311. {
  312. if (app->main_api.arep != UINT32_MAX)
  313. {
  314. APP_LOG_WARNING ("Warning - AREP out of sync\n");
  315. }
  316. app->main_api.arep = arep;
  317. app_set_initial_data_and_ioxs (app);
  318. (void)pnet_set_provider_state (net, true);
  319. /* Send application ready at next tick
  320. Do not call pnet_application_ready() here as it will affect
  321. the internal stack states */
  322. app->arep_for_appl_ready = arep;
  323. os_event_set (app->main_events, APP_EVENT_READY_FOR_DATA);
  324. }
  325. else if (state == PNET_EVENT_DATA)
  326. {
  327. APP_LOG_DEBUG ("Cyclic data transmission started\n\n");
  328. }
  329. return 0;
  330. }
  331. static int app_reset_ind (
  332. pnet_t * net,
  333. void * arg,
  334. bool should_reset_application,
  335. uint16_t reset_mode)
  336. {
  337. APP_LOG_DEBUG (
  338. "PLC reset indication. Application reset mandatory: %u Reset mode: %d\n",
  339. should_reset_application,
  340. reset_mode);
  341. return 0;
  342. }
  343. static int app_signal_led_ind (pnet_t * net, void * arg, bool led_state)
  344. {
  345. APP_LOG_INFO ("Profinet signal LED indication. New state: %u\n", led_state);
  346. app_set_led (APP_PROFINET_SIGNAL_LED_ID, led_state);
  347. return 0;
  348. }
  349. static int app_exp_module_ind (
  350. pnet_t * net,
  351. void * arg,
  352. uint32_t api,
  353. uint16_t slot,
  354. uint32_t module_ident)
  355. {
  356. int ret = -1;
  357. int result = 0;
  358. app_data_t * app = (app_data_t *)arg;
  359. const char * module_name = "unknown";
  360. const app_gsdml_module_t * module_config;
  361. APP_LOG_DEBUG ("Module plug indication API %d\n");
  362. if (slot >= PNET_MAX_SLOTS)
  363. {
  364. APP_LOG_ERROR (
  365. "Unsupported slot number: %u It should be less than %u\n",
  366. slot,
  367. PNET_MAX_SLOTS);
  368. return -1;
  369. }
  370. module_config = app_gsdml_get_module_cfg (module_ident);
  371. if (module_config == NULL)
  372. {
  373. APP_LOG_ERROR (" Module ID %08x not found.\n", (unsigned)module_ident);
  374. /*
  375. * Needed to pass Behavior scenario 2
  376. */
  377. APP_LOG_DEBUG (" Plug expected module anyway\n");
  378. }
  379. else
  380. {
  381. module_name = module_config->name;
  382. }
  383. APP_LOG_DEBUG (" [%u] Pull old module\n", slot);
  384. result = pnet_pull_module (net, api, slot);
  385. if (result == 0)
  386. {
  387. app_utils_pull_module (&app->main_api, slot);
  388. }
  389. APP_LOG_DEBUG (
  390. " [%u] Plug module. Module ID: 0x%x \"%s\"\n",
  391. slot,
  392. (unsigned)module_ident,
  393. module_name);
  394. ret = pnet_plug_module (net, api, slot, module_ident);
  395. if (ret == 0)
  396. {
  397. app_utils_plug_module (&app->main_api, slot, module_ident, module_name);
  398. }
  399. else
  400. {
  401. APP_LOG_ERROR (
  402. " [%u] Plug module failed. Ret: %u Module ID: 0x%x \" \"\n",
  403. slot,
  404. ret,
  405. (unsigned)module_ident,
  406. module_name);
  407. }
  408. return ret;
  409. }
  410. static int app_exp_submodule_ind (
  411. pnet_t * net,
  412. void * arg,
  413. uint32_t api,
  414. uint16_t slot,
  415. uint16_t subslot,
  416. uint32_t module_id,
  417. uint32_t submodule_id,
  418. const pnet_data_cfg_t * p_exp_data)
  419. {
  420. int ret = -1;
  421. int result = 0;
  422. pnet_data_cfg_t data_cfg = {0};
  423. app_data_t * app = (app_data_t *)arg;
  424. const app_gsdml_submodule_t * submod_cfg;
  425. const char * name = "Unsupported";
  426. app_utils_cyclic_callback cyclic_data_callback = NULL;
  427. app_subslot_t * p_subslot;
  428. APP_LOG_DEBUG ("Submodule plug indication API %u\n", api);
  429. submod_cfg = app_gsdml_get_submodule_cfg (submodule_id);
  430. if (submod_cfg != NULL)
  431. {
  432. data_cfg.data_dir = submod_cfg->data_dir;
  433. data_cfg.insize = submod_cfg->insize;
  434. data_cfg.outsize = submod_cfg->outsize;
  435. name = submod_cfg->name;
  436. if (data_cfg.insize > 0 || data_cfg.outsize > 0)
  437. {
  438. cyclic_data_callback = app_cyclic_data_callback;
  439. }
  440. }
  441. else
  442. {
  443. APP_LOG_WARNING (
  444. " [%u,%u] Submodule ID 0x%x in Module ID 0x%x not found \n",
  445. slot,
  446. subslot,
  447. (unsigned)submodule_id,
  448. (unsigned)module_id);
  449. /*
  450. * Needed for behavior scenario 2 to pass.
  451. * Iops will be set to bad for this subslot
  452. */
  453. APP_LOG_WARNING (
  454. " [%u,%u] Plug expected submodule anyway\n",
  455. slot,
  456. subslot);
  457. data_cfg.data_dir = p_exp_data->data_dir;
  458. data_cfg.insize = p_exp_data->insize;
  459. data_cfg.outsize = p_exp_data->outsize;
  460. }
  461. APP_LOG_DEBUG (" [%u,%u] Pull old submodule.\n", slot, subslot);
  462. result = pnet_pull_submodule (net, api, slot, subslot);
  463. if (result == 0)
  464. {
  465. app_utils_pull_submodule (&app->main_api, slot, subslot);
  466. }
  467. APP_LOG_DEBUG (
  468. " [%u,%u] Plug submodule. Submodule ID: 0x%x Data Dir: %s In: %u Out: "
  469. "%u \"%s\"\n",
  470. slot,
  471. subslot,
  472. (unsigned)submodule_id,
  473. app_utils_submod_dir_to_string (data_cfg.data_dir),
  474. data_cfg.insize,
  475. data_cfg.outsize,
  476. name);
  477. if (
  478. data_cfg.data_dir != p_exp_data->data_dir ||
  479. data_cfg.insize != p_exp_data->insize ||
  480. data_cfg.outsize != p_exp_data->outsize)
  481. {
  482. APP_LOG_WARNING (
  483. " [%u,%u] Warning expected Data Dir: %s In: %u Out: %u\n",
  484. slot,
  485. subslot,
  486. app_utils_submod_dir_to_string (p_exp_data->data_dir),
  487. p_exp_data->insize,
  488. p_exp_data->outsize);
  489. }
  490. ret = pnet_plug_submodule (
  491. net,
  492. api,
  493. slot,
  494. subslot,
  495. module_id,
  496. submodule_id,
  497. data_cfg.data_dir,
  498. data_cfg.insize,
  499. data_cfg.outsize);
  500. if (ret == 0)
  501. {
  502. p_subslot = app_utils_plug_submodule (
  503. &app->main_api,
  504. slot,
  505. subslot,
  506. submodule_id,
  507. &data_cfg,
  508. name,
  509. cyclic_data_callback,
  510. app);
  511. /**
  512. * Setup the RTE configuration for submodules data provided by the FPGA.
  513. */
  514. if (app->mode == MODE_HW_OFFLOAD_FULL)
  515. {
  516. const uint8_t * default_data;
  517. uint16_t fpga_address;
  518. if (
  519. app_data_get_fpga_info_by_id (
  520. submodule_id,
  521. &fpga_address,
  522. &default_data) == 0)
  523. {
  524. pnet_mera_rte_data_cfg_t rte_cfg = {
  525. .type = PNET_MERA_DATA_TYPE_QSPI,
  526. .address = fpga_address,
  527. .default_data = default_data};
  528. APP_LOG_INFO (
  529. " %-40s Set RTE QSPI address 0x%x\n",
  530. app_utils_get_subslot_string (p_subslot),
  531. rte_cfg.address);
  532. if (data_cfg.insize > 0)
  533. {
  534. if (
  535. pnet_mera_input_set_rte_config (
  536. app->net,
  537. APP_GSDML_API,
  538. slot,
  539. subslot,
  540. &rte_cfg) != 0)
  541. {
  542. APP_LOG_ERROR (
  543. " %-40s RTE configuration failed\n",
  544. app_utils_get_subslot_string (p_subslot));
  545. }
  546. }
  547. else
  548. {
  549. if (
  550. pnet_mera_output_set_rte_config (
  551. app->net,
  552. APP_GSDML_API,
  553. slot,
  554. subslot,
  555. &rte_cfg) != 0)
  556. {
  557. APP_LOG_ERROR (
  558. " %-40s RTE configuration failed\n",
  559. app_utils_get_subslot_string (p_subslot));
  560. }
  561. }
  562. }
  563. }
  564. }
  565. else
  566. {
  567. APP_LOG_ERROR (
  568. " [%u,%u] Plug submodule failed. Ret: %u\n",
  569. slot,
  570. subslot,
  571. ret);
  572. }
  573. return ret;
  574. }
  575. static int app_new_data_status_ind (
  576. pnet_t * net,
  577. void * arg,
  578. uint32_t arep,
  579. uint32_t crep,
  580. uint8_t changes,
  581. uint8_t data_status)
  582. {
  583. bool is_running = data_status & BIT (PNET_DATA_STATUS_BIT_PROVIDER_STATE);
  584. bool is_valid = data_status & BIT (PNET_DATA_STATUS_BIT_DATA_VALID);
  585. APP_LOG_DEBUG (
  586. "Data status indication. AREP: %u Data status changes: 0x%02x "
  587. "Data status: 0x%02x\n",
  588. arep,
  589. changes,
  590. data_status);
  591. APP_LOG_DEBUG (
  592. " %s, %s, %s, %s, %s\n",
  593. is_running ? "Run" : "Stop",
  594. is_valid ? "Valid" : "Invalid",
  595. (data_status & BIT (PNET_DATA_STATUS_BIT_STATE)) ? "Primary" : "Backup",
  596. (data_status & BIT (PNET_DATA_STATUS_BIT_STATION_PROBLEM_INDICATOR))
  597. ? "Normal operation"
  598. : "Problem",
  599. (data_status & BIT (PNET_DATA_STATUS_BIT_IGNORE))
  600. ? "Ignore data status"
  601. : "Evaluate data status");
  602. if (is_running == false || is_valid == false)
  603. {
  604. app_set_outputs_default_value();
  605. }
  606. return 0;
  607. }
  608. static int app_alarm_ind (
  609. pnet_t * net,
  610. void * arg,
  611. uint32_t arep,
  612. const pnet_alarm_argument_t * p_alarm_arg,
  613. uint16_t data_len,
  614. uint16_t data_usi,
  615. const uint8_t * p_data)
  616. {
  617. app_data_t * app = (app_data_t *)arg;
  618. APP_LOG_DEBUG (
  619. "Alarm indication. AREP: %u API: %d Slot: %d Subslot: %d "
  620. "Type: %d Seq: %d Length: %d USI: %d\n",
  621. arep,
  622. p_alarm_arg->api_id,
  623. p_alarm_arg->slot_nbr,
  624. p_alarm_arg->subslot_nbr,
  625. p_alarm_arg->alarm_type,
  626. p_alarm_arg->sequence_number,
  627. data_len,
  628. data_usi);
  629. app->alarm_arg = *p_alarm_arg;
  630. os_event_set (app->main_events, APP_EVENT_ALARM);
  631. return 0;
  632. }
  633. static int app_alarm_cnf (
  634. pnet_t * net,
  635. void * arg,
  636. uint32_t arep,
  637. const pnet_pnio_status_t * p_pnio_status)
  638. {
  639. app_data_t * app = (app_data_t *)arg;
  640. APP_LOG_DEBUG (
  641. "PLC alarm confirmation. AREP: %u Status code %u, "
  642. "%u, %u, %u\n",
  643. arep,
  644. p_pnio_status->error_code,
  645. p_pnio_status->error_decode,
  646. p_pnio_status->error_code_1,
  647. p_pnio_status->error_code_2);
  648. app->alarm_allowed = true;
  649. return 0;
  650. }
  651. static int app_alarm_ack_cnf (pnet_t * net, void * arg, uint32_t arep, int res)
  652. {
  653. APP_LOG_DEBUG (
  654. "PLC alarm ACK confirmation. AREP: %u Result: "
  655. "%d\n",
  656. arep,
  657. res);
  658. return 0;
  659. }
  660. /**
  661. * Plug all DAP (sub)modules
  662. * Use existing callback functions to plug the (sub-)modules
  663. * @param app InOut: Application handle
  664. * @param number_of_ports In: Number of active ports
  665. */
  666. static void app_plug_dap (app_data_t * app, uint16_t number_of_ports)
  667. {
  668. const pnet_data_cfg_t cfg_dap_data = {
  669. .data_dir = PNET_DIR_NO_IO,
  670. .insize = 0,
  671. .outsize = 0,
  672. };
  673. APP_LOG_DEBUG ("Plug DAP module and its submodules\n");
  674. app_exp_module_ind (
  675. app->net,
  676. app,
  677. APP_GSDML_API,
  678. PNET_SLOT_DAP_IDENT,
  679. PNET_MOD_DAP_IDENT);
  680. app_exp_submodule_ind (
  681. app->net,
  682. app,
  683. APP_GSDML_API,
  684. PNET_SLOT_DAP_IDENT,
  685. PNET_SUBSLOT_DAP_IDENT,
  686. PNET_MOD_DAP_IDENT,
  687. PNET_SUBMOD_DAP_IDENT,
  688. &cfg_dap_data);
  689. app_exp_submodule_ind (
  690. app->net,
  691. app,
  692. APP_GSDML_API,
  693. PNET_SLOT_DAP_IDENT,
  694. PNET_SUBSLOT_DAP_INTERFACE_1_IDENT,
  695. PNET_MOD_DAP_IDENT,
  696. PNET_SUBMOD_DAP_INTERFACE_1_IDENT,
  697. &cfg_dap_data);
  698. app_exp_submodule_ind (
  699. app->net,
  700. app,
  701. APP_GSDML_API,
  702. PNET_SLOT_DAP_IDENT,
  703. PNET_SUBSLOT_DAP_INTERFACE_1_PORT_1_IDENT,
  704. PNET_MOD_DAP_IDENT,
  705. PNET_SUBMOD_DAP_INTERFACE_1_PORT_1_IDENT,
  706. &cfg_dap_data);
  707. if (number_of_ports >= 2)
  708. {
  709. app_exp_submodule_ind (
  710. app->net,
  711. app,
  712. APP_GSDML_API,
  713. PNET_SLOT_DAP_IDENT,
  714. PNET_SUBSLOT_DAP_INTERFACE_1_PORT_2_IDENT,
  715. PNET_MOD_DAP_IDENT,
  716. PNET_SUBMOD_DAP_INTERFACE_1_PORT_2_IDENT,
  717. &cfg_dap_data);
  718. }
  719. if (number_of_ports >= 3)
  720. {
  721. app_exp_submodule_ind (
  722. app->net,
  723. app,
  724. APP_GSDML_API,
  725. PNET_SLOT_DAP_IDENT,
  726. PNET_SUBSLOT_DAP_INTERFACE_1_PORT_3_IDENT,
  727. PNET_MOD_DAP_IDENT,
  728. PNET_SUBMOD_DAP_INTERFACE_1_PORT_3_IDENT,
  729. &cfg_dap_data);
  730. }
  731. if (number_of_ports >= 4)
  732. {
  733. app_exp_submodule_ind (
  734. app->net,
  735. app,
  736. APP_GSDML_API,
  737. PNET_SLOT_DAP_IDENT,
  738. PNET_SUBSLOT_DAP_INTERFACE_1_PORT_4_IDENT,
  739. PNET_MOD_DAP_IDENT,
  740. PNET_SUBMOD_DAP_INTERFACE_1_PORT_4_IDENT,
  741. &cfg_dap_data);
  742. }
  743. }
  744. /**
  745. * Send application ready to the PLC
  746. * @param net InOut: p-net stack instance
  747. * @param arep In: Arep
  748. */
  749. static void app_handle_send_application_ready (pnet_t * net, uint32_t arep)
  750. {
  751. int ret = -1;
  752. APP_LOG_DEBUG (
  753. "Application will signal that it is ready for data, for "
  754. "AREP %u.\n",
  755. arep);
  756. ret = pnet_application_ready (net, arep);
  757. if (ret != 0)
  758. {
  759. APP_LOG_ERROR (
  760. "Error returned when application telling that it is ready for "
  761. "data. Have you set IOCS or IOPS for all subslots?\n");
  762. }
  763. /* When the PLC sends a confirmation to this message, the
  764. pnet_ccontrol_cnf() callback will be triggered. */
  765. }
  766. /**
  767. * Send alarm ACK to the PLC
  768. *
  769. * @param net InOut: p-net stack instance
  770. * @param arep In: Arep
  771. * @param p_alarm_arg In: Alarm argument (slot, subslot etc)
  772. */
  773. static void app_handle_send_alarm_ack (
  774. pnet_t * net,
  775. uint32_t arep,
  776. const pnet_alarm_argument_t * p_alarm_arg)
  777. {
  778. pnet_pnio_status_t pnio_status = {0, 0, 0, 0};
  779. int ret;
  780. ret = pnet_alarm_send_ack (net, arep, p_alarm_arg, &pnio_status);
  781. if (ret != 0)
  782. {
  783. APP_LOG_DEBUG ("Error when sending alarm ACK. Error: %d\n", ret);
  784. }
  785. else
  786. {
  787. APP_LOG_DEBUG ("Alarm ACK sent\n");
  788. }
  789. }
  790. /**
  791. * Handle cyclic data for all plugged submodules
  792. * Data is read from / written to the app_data file
  793. * which handles the data and update the physical
  794. * input /outputs.
  795. *
  796. * For subslots with mapped shared memory inputs, the
  797. * shared memory is read and the data is passed to the
  798. * stack.
  799. *
  800. * For subslots with mapped shared memory outputs, the
  801. * current output data is fetched from the stack and written to
  802. * mapped shared memory.
  803. *
  804. * @param subslot In: Subslot reference
  805. * @param tag In: Application handle
  806. */
  807. static void app_cyclic_data_callback (app_subslot_t * subslot, void * tag)
  808. {
  809. app_data_t * app = (app_data_t *)tag;
  810. uint8_t iops = PNET_IOXS_BAD;
  811. uint8_t iocs = PNET_IOXS_BAD;
  812. uint8_t * indata;
  813. uint16_t indata_size;
  814. bool outdata_updated;
  815. uint16_t outdata_length;
  816. uint8_t outdata_iops;
  817. uint8_t * outdata;
  818. if (app == NULL)
  819. {
  820. APP_LOG_ERROR ("Application tag not set in subslot?\n");
  821. return;
  822. }
  823. if (subslot->data_cfg.insize > 0)
  824. {
  825. indata =
  826. app_data_get_input_data (subslot->submodule_id, &indata_size, &iops);
  827. if (indata != NULL)
  828. {
  829. iops = PNET_IOXS_GOOD;
  830. }
  831. (void)pnet_input_set_data_and_iops (
  832. app->net,
  833. APP_GSDML_API,
  834. subslot->slot_nbr,
  835. subslot->subslot_nbr,
  836. indata,
  837. indata_size,
  838. iops);
  839. (void)pnet_input_get_iocs (
  840. app->net,
  841. APP_GSDML_API,
  842. subslot->slot_nbr,
  843. subslot->subslot_nbr,
  844. &iocs);
  845. app_utils_print_ioxs_change (
  846. subslot,
  847. "Consumer Status (IOCS)",
  848. subslot->indata_iocs,
  849. iocs);
  850. subslot->indata_iocs = iocs;
  851. }
  852. if (subslot->data_cfg.outsize > 0)
  853. {
  854. outdata = app_data_get_output_data_buffer (
  855. subslot->submodule_id,
  856. &outdata_length);
  857. pnet_output_get_data_and_iops (
  858. app->net,
  859. APP_GSDML_API,
  860. subslot->slot_nbr,
  861. subslot->subslot_nbr,
  862. &outdata_updated,
  863. outdata,
  864. &outdata_length,
  865. &outdata_iops);
  866. app_utils_print_ioxs_change (
  867. subslot,
  868. "Provider Status (IOPS)",
  869. subslot->outdata_iops,
  870. outdata_iops);
  871. subslot->outdata_iops = outdata_iops;
  872. if (outdata_length != subslot->data_cfg.outsize)
  873. {
  874. APP_LOG_ERROR (
  875. " %-40s Wrong outputdata length %u (%u)\n",
  876. app_utils_get_subslot_string (subslot),
  877. outdata_length,
  878. subslot->data_cfg.outsize);
  879. app_set_outputs_default_value();
  880. }
  881. else if (outdata_iops == PNET_IOXS_GOOD)
  882. {
  883. /* Set output data for submodule */
  884. app_data_set_output_data (
  885. subslot->submodule_id,
  886. outdata,
  887. outdata_length);
  888. }
  889. else
  890. {
  891. app_set_outputs_default_value();
  892. }
  893. }
  894. }
  895. /**
  896. * Set initial input data, provider and consumer status for a subslot.
  897. *
  898. * @param app In: Application handle
  899. */
  900. static int app_set_initial_data_and_ioxs (app_data_t * app)
  901. {
  902. int ret;
  903. uint8_t iops;
  904. uint16_t slot;
  905. uint16_t subslot;
  906. const app_subslot_t * p_subslot;
  907. uint8_t * indata;
  908. uint16_t indata_size;
  909. for (slot = 0; slot < PNET_MAX_SLOTS; slot++)
  910. {
  911. for (subslot = 0; subslot < PNET_MAX_SUBSLOTS; subslot++)
  912. {
  913. p_subslot = &app->main_api.slots[slot].subslots[subslot];
  914. if (p_subslot->plugged)
  915. {
  916. iops = PNET_IOXS_GOOD;
  917. if (
  918. p_subslot->data_cfg.insize > 0 ||
  919. p_subslot->data_cfg.data_dir == PNET_DIR_NO_IO)
  920. {
  921. indata = NULL;
  922. indata_size = p_subslot->data_cfg.insize;
  923. if (p_subslot->data_cfg.insize > 0)
  924. {
  925. indata = app_data_get_input_data (
  926. p_subslot->submodule_id,
  927. &indata_size,
  928. &iops);
  929. }
  930. ret = pnet_input_set_data_and_iops (
  931. app->net,
  932. APP_GSDML_API,
  933. p_subslot->slot_nbr,
  934. p_subslot->subslot_nbr,
  935. indata,
  936. indata_size,
  937. iops);
  938. /*
  939. * If a submodule is still plugged but not used in current
  940. * AR setting the data and iops will fail. This is not a
  941. * problem. Log message below will only be printed for
  942. * active submodules.
  943. */
  944. if (ret == 0)
  945. {
  946. APP_LOG_DEBUG (
  947. " %-40s Set input data and IOPS. Size: %d "
  948. "IOPS: %s\n",
  949. app_utils_get_subslot_string (p_subslot),
  950. p_subslot->data_cfg.insize,
  951. app_utils_ioxs_to_string (iops));
  952. }
  953. }
  954. if (p_subslot->data_cfg.outsize > 0)
  955. {
  956. ret = pnet_output_set_iocs (
  957. app->net,
  958. APP_GSDML_API,
  959. p_subslot->slot_nbr,
  960. p_subslot->subslot_nbr,
  961. PNET_IOXS_GOOD);
  962. if (ret == 0)
  963. {
  964. APP_LOG_DEBUG (
  965. " %-40s Set output IOCS: %s\n",
  966. app_utils_get_subslot_string (p_subslot),
  967. app_utils_ioxs_to_string (PNET_IOXS_GOOD));
  968. }
  969. }
  970. }
  971. }
  972. }
  973. return 0;
  974. }
  975. /**
  976. * Send and receive cyclic / process data
  977. *
  978. * Generate callback for all plugged submodules
  979. * the sample application handles all submodules
  980. * in the app_cyclic_data_callback() function.
  981. * A complex device may register separate callbacks
  982. * for each submodule.
  983. *
  984. * @param app In: Application handle
  985. */
  986. static void app_handle_cyclic_data (app_data_t * app)
  987. {
  988. /* For the sample application cyclic data is updated
  989. * with a period defined by APP_TICKS_UPDATE_DATA
  990. */
  991. app->process_data_tick_counter++;
  992. if (app->process_data_tick_counter < APP_TICKS_UPDATE_DATA)
  993. {
  994. return;
  995. }
  996. app->process_data_tick_counter = 0;
  997. app_utils_cyclic_data_poll (&app->main_api);
  998. }
  999. void app_pnet_cfg_init_default (pnet_cfg_t * pnet_cfg)
  1000. {
  1001. app_utils_pnet_cfg_init_default (pnet_cfg);
  1002. pnet_cfg->state_cb = app_state_ind;
  1003. pnet_cfg->connect_cb = app_connect_ind;
  1004. pnet_cfg->release_cb = app_release_ind;
  1005. pnet_cfg->dcontrol_cb = app_dcontrol_ind;
  1006. pnet_cfg->ccontrol_cb = app_ccontrol_cnf;
  1007. pnet_cfg->read_cb = app_read_ind;
  1008. pnet_cfg->write_cb = app_write_ind;
  1009. pnet_cfg->exp_module_cb = app_exp_module_ind;
  1010. pnet_cfg->exp_submodule_cb = app_exp_submodule_ind;
  1011. pnet_cfg->new_data_status_cb = app_new_data_status_ind;
  1012. pnet_cfg->alarm_ind_cb = app_alarm_ind;
  1013. pnet_cfg->alarm_cnf_cb = app_alarm_cnf;
  1014. pnet_cfg->alarm_ack_cnf_cb = app_alarm_ack_cnf;
  1015. pnet_cfg->reset_cb = app_reset_ind;
  1016. pnet_cfg->signal_led_cb = app_signal_led_ind;
  1017. pnet_cfg->cb_arg = (void *)&app_state;
  1018. }
  1019. void app_loop_forever (void * arg)
  1020. {
  1021. app_data_t * app = (app_data_t *)arg;
  1022. uint32_t mask = APP_EVENT_READY_FOR_DATA | APP_EVENT_TIMER |
  1023. APP_EVENT_ALARM | APP_EVENT_ABORT;
  1024. uint32_t flags = 0;
  1025. app->main_api.arep = UINT32_MAX;
  1026. app_set_led (APP_DATA_LED_ID, false);
  1027. app_plug_dap (app, app->pnet_cfg->num_physical_ports);
  1028. APP_LOG_INFO ("Waiting for PLC connect request\n\n");
  1029. /* Main event loop */
  1030. for (;;)
  1031. {
  1032. os_event_wait (app->main_events, mask, &flags, OS_WAIT_FOREVER);
  1033. if (flags & APP_EVENT_READY_FOR_DATA)
  1034. {
  1035. /* Delay the application ready event to
  1036. * allow the RTE to start sending frames.
  1037. */
  1038. app->appl_ready_delay_count = 256;
  1039. app->appl_ready_wait = true;
  1040. os_event_clr (app->main_events, APP_EVENT_READY_FOR_DATA);
  1041. }
  1042. else if (flags & APP_EVENT_ALARM)
  1043. {
  1044. os_event_clr (app->main_events, APP_EVENT_ALARM);
  1045. app_handle_send_alarm_ack (
  1046. app->net,
  1047. app->main_api.arep,
  1048. &app->alarm_arg);
  1049. }
  1050. else if (flags & APP_EVENT_TIMER)
  1051. {
  1052. os_event_clr (app->main_events, APP_EVENT_TIMER);
  1053. if (app->appl_ready_wait)
  1054. {
  1055. /* Delayed application ready event */
  1056. if (app->appl_ready_delay_count == 0)
  1057. {
  1058. app->appl_ready_wait = false;
  1059. app_handle_send_application_ready (
  1060. app->net,
  1061. app->arep_for_appl_ready);
  1062. }
  1063. else
  1064. {
  1065. app->appl_ready_delay_count--;
  1066. }
  1067. }
  1068. if (app->main_api.arep != UINT32_MAX)
  1069. {
  1070. /* Todo this operation should be split
  1071. * and inputs handled before pnet_handle_periodic is
  1072. * called and outputs after.*/
  1073. app_handle_cyclic_data (app);
  1074. }
  1075. /* Run p-net stack */
  1076. pnet_handle_periodic (app->net);
  1077. }
  1078. else if (flags & APP_EVENT_ABORT)
  1079. {
  1080. os_event_clr (app->main_events, APP_EVENT_ABORT);
  1081. app->main_api.arep = UINT32_MAX;
  1082. app->alarm_allowed = true;
  1083. APP_LOG_DEBUG ("Connection closed\n");
  1084. APP_LOG_DEBUG ("Waiting for PLC connect request\n\n");
  1085. }
  1086. }
  1087. }