Commit 084e7e6a0fef23375eb85663457105f2cfdd1c9c

Authored by Stéphane Raimbault
1 parent a1513415

- Catch the timeout even if the length is equal to a exception trame.

- Add many comments to receive_msg and modbus_receive functions.
- The use of response_length for good response was confusing.
Showing 1 changed file with 74 additions and 64 deletions
modbus/modbus.c
@@ -445,19 +445,23 @@ static int compute_query_length_data(modbus_param_t *mb_param, uint8_t *msg) @@ -445,19 +445,23 @@ static int compute_query_length_data(modbus_param_t *mb_param, uint8_t *msg)
445 } \ 445 } \
446 } 446 }
447 447
448 -/* Monitors for the reply from the modbus slave or to receive query  
449 - from a modbus master. 448 +/* Waits a reply from a modbus slave or a query from a modbus master.
450 This function blocks for timeout seconds if there is no reply. 449 This function blocks for timeout seconds if there is no reply.
451 450
452 - - msg is an array of uint8_t to receive the message 451 + In
453 - msg_length_computed must be set to MSG_LENGTH_UNDEFINED if undefined 452 - msg_length_computed must be set to MSG_LENGTH_UNDEFINED if undefined
454 453
455 - Returns a negative number if an error occured.  
456 - The variable msg_length is assigned to the number of characters  
457 - received. */  
458 -int receive_msg(modbus_param_t *mb_param,  
459 - int msg_length_computed,  
460 - uint8_t *msg, int *msg_length) 454 + Out
  455 + - msg is an array of uint8_t to receive the message
  456 + - p_msg_length, the variable is assigned to the number of
  457 + characters received. This value won't be greater than
  458 + msg_length_computed.
  459 +
  460 + Returns 0 in success or a negative value if an error occured.
  461 +*/
  462 +static int receive_msg(modbus_param_t *mb_param,
  463 + int msg_length_computed,
  464 + uint8_t *msg, int *p_msg_length)
461 { 465 {
462 int select_ret; 466 int select_ret;
463 int read_ret; 467 int read_ret;
@@ -502,8 +506,8 @@ int receive_msg(modbus_param_t *mb_param, @@ -502,8 +506,8 @@ int receive_msg(modbus_param_t *mb_param,
502 select_ret = 0; 506 select_ret = 0;
503 WAIT_DATA(); 507 WAIT_DATA();
504 508
505 - /* Read the msg */  
506 - (*msg_length) = 0; 509 + /* Initialize the readin the message */
  510 + (*p_msg_length) = 0;
507 p_msg = msg; 511 p_msg = msg;
508 512
509 while (select_ret) { 513 while (select_ret) {
@@ -523,7 +527,7 @@ int receive_msg(modbus_param_t *mb_param, @@ -523,7 +527,7 @@ int receive_msg(modbus_param_t *mb_param,
523 } 527 }
524 528
525 /* Sums bytes received */ 529 /* Sums bytes received */
526 - (*msg_length) += read_ret; 530 + (*p_msg_length) += read_ret;
527 531
528 /* Display the hex code of each character received */ 532 /* Display the hex code of each character received */
529 if (mb_param->debug) { 533 if (mb_param->debug) {
@@ -532,9 +536,9 @@ int receive_msg(modbus_param_t *mb_param, @@ -532,9 +536,9 @@ int receive_msg(modbus_param_t *mb_param,
532 printf("<%.2X>", p_msg[i]); 536 printf("<%.2X>", p_msg[i]);
533 } 537 }
534 538
535 - if ((*msg_length) < msg_length_computed) { 539 + if ((*p_msg_length) < msg_length_computed) {
536 /* Message incomplete */ 540 /* Message incomplete */
537 - length_to_read = msg_length_computed - (*msg_length); 541 + length_to_read = msg_length_computed - (*p_msg_length);
538 } else { 542 } else {
539 switch (state) { 543 switch (state) {
540 case FUNCTION: 544 case FUNCTION:
@@ -542,7 +546,7 @@ int receive_msg(modbus_param_t *mb_param, @@ -542,7 +546,7 @@ int receive_msg(modbus_param_t *mb_param,
542 length_to_read = compute_query_length_header(msg[mb_param->header_length + 1]); 546 length_to_read = compute_query_length_header(msg[mb_param->header_length + 1]);
543 msg_length_computed += length_to_read; 547 msg_length_computed += length_to_read;
544 /* It's useless to check 548 /* It's useless to check
545 - msg_length_computed value in this 549 + p_msg_length_computed value in this
546 case (only defined values are used). */ 550 case (only defined values are used). */
547 state = BYTE; 551 state = BYTE;
548 break; 552 break;
@@ -581,7 +585,7 @@ int receive_msg(modbus_param_t *mb_param, @@ -581,7 +585,7 @@ int receive_msg(modbus_param_t *mb_param,
581 printf("\n"); 585 printf("\n");
582 586
583 if (mb_param->type_com == RTU) { 587 if (mb_param->type_com == RTU) {
584 - check_crc16(mb_param, msg, *msg_length); 588 + check_crc16(mb_param, msg, (*p_msg_length));
585 } 589 }
586 590
587 /* OK */ 591 /* OK */
@@ -592,7 +596,8 @@ int receive_msg(modbus_param_t *mb_param, @@ -592,7 +596,8 @@ int receive_msg(modbus_param_t *mb_param,
592 /* Receives the response and checks values (and checksum in RTU). 596 /* Receives the response and checks values (and checksum in RTU).
593 597
594 Returns: 598 Returns:
595 - - the numbers of values (bits or word) if success 599 + - the number of values (bits or word) if success or the response
  600 + length if no value is returned
596 - less than 0 for exception errors 601 - less than 0 for exception errors
597 602
598 Note: all functions used to send or receive data with modbus return 603 Note: all functions used to send or receive data with modbus return
@@ -601,10 +606,10 @@ static int modbus_receive(modbus_param_t *mb_param, @@ -601,10 +606,10 @@ static int modbus_receive(modbus_param_t *mb_param,
601 uint8_t *query, 606 uint8_t *query,
602 uint8_t *response) 607 uint8_t *response)
603 { 608 {
  609 + int ret;
604 int response_length; 610 int response_length;
605 - int response_length_computed; 611 + int response_length_computed;
606 int offset = mb_param->header_length; 612 int offset = mb_param->header_length;
607 - int ret;  
608 613
609 response_length_computed = compute_response_length(mb_param, query); 614 response_length_computed = compute_response_length(mb_param, query);
610 ret = receive_msg(mb_param, response_length_computed, 615 ret = receive_msg(mb_param, response_length_computed,
@@ -612,21 +617,23 @@ static int modbus_receive(modbus_param_t *mb_param, @@ -612,21 +617,23 @@ static int modbus_receive(modbus_param_t *mb_param,
612 if (ret == 0) { 617 if (ret == 0) {
613 /* GOOD RESPONSE */ 618 /* GOOD RESPONSE */
614 619
  620 + /* The number of values is returned for the following
  621 + * cases */
615 switch (response[offset + 1]) { 622 switch (response[offset + 1]) {
616 case FC_READ_COIL_STATUS: 623 case FC_READ_COIL_STATUS:
617 case FC_READ_INPUT_STATUS: 624 case FC_READ_INPUT_STATUS:
618 /* Read functions 1 value = 1 byte */ 625 /* Read functions 1 value = 1 byte */
619 - response_length = response[offset + 2]; 626 + ret = response[offset + 2];
620 break; 627 break;
621 case FC_READ_HOLDING_REGISTERS: 628 case FC_READ_HOLDING_REGISTERS:
622 case FC_READ_INPUT_REGISTERS: 629 case FC_READ_INPUT_REGISTERS:
623 /* Read functions 1 value = 2 bytes */ 630 /* Read functions 1 value = 2 bytes */
624 - response_length = response[offset + 2] / 2; 631 + ret = response[offset + 2] / 2;
625 break; 632 break;
626 case FC_FORCE_MULTIPLE_COILS: 633 case FC_FORCE_MULTIPLE_COILS:
627 case FC_PRESET_MULTIPLE_REGISTERS: 634 case FC_PRESET_MULTIPLE_REGISTERS:
628 /* N Write functions */ 635 /* N Write functions */
629 - response_length = response[offset + 4] << 8 | 636 + ret = response[offset + 4] << 8 |
630 response[offset + 5]; 637 response[offset + 5];
631 break; 638 break;
632 case FC_REPORT_SLAVE_ID: 639 case FC_REPORT_SLAVE_ID:
@@ -634,60 +641,62 @@ static int modbus_receive(modbus_param_t *mb_param, @@ -634,60 +641,62 @@ static int modbus_receive(modbus_param_t *mb_param,
634 break; 641 break;
635 default: 642 default:
636 /* 1 Write functions & others */ 643 /* 1 Write functions & others */
637 - response_length = 1; 644 + ret = 1;
638 } 645 }
  646 + } else if (ret == COMM_TIME_OUT) {
639 647
640 - } else if (ret == COMM_TIME_OUT &&  
641 - response_length == offset + 3 + mb_param->checksum_length) {  
642 - /* EXCEPTION CODE RECEIVED */ 648 + if (response_length == (offset + 3 + mb_param->checksum_length)) {
  649 + /* EXCEPTION CODE RECEIVED */
643 650
644 - /* Optimization allowed because exception response is  
645 - the smallest trame in modbus protocol (3) so always  
646 - raise a timeout error */ 651 + /* Optimization allowed because exception response is
  652 + the smallest trame in modbus protocol (3) so always
  653 + raise a timeout error */
647 654
648 - /* CRC must be checked here (not done in receive_msg) */  
649 - if (mb_param->type_com == RTU) {  
650 - ret = check_crc16(mb_param, response, response_length);  
651 - if (ret != 0)  
652 - return ret;  
653 - } 655 + /* CRC must be checked here (not done in receive_msg) */
  656 + if (mb_param->type_com == RTU) {
  657 + ret = check_crc16(mb_param, response, response_length);
  658 + if (ret != 0)
  659 + return ret;
  660 + }
654 661
655 - /* Check for exception response.  
656 - 0x80 + function is stored in the exception  
657 - response. */  
658 - if (0x80 + query[offset + 1] == response[offset + 1]) {  
659 -  
660 - int exception_code = response[offset + 2];  
661 - // FIXME check test  
662 - if (exception_code < NB_TAB_ERROR_MSG) {  
663 - error_treat(mb_param, -exception_code,  
664 - TAB_ERROR_MSG[response[offset + 2]]);  
665 - /* Modbus error code is negative */  
666 - return -exception_code;  
667 - } else {  
668 - /* The chances are low to hit this  
669 - case but it can avoid a vicious  
670 - segfault */  
671 - char *s_error = malloc(64 * sizeof(char));  
672 - sprintf(s_error,  
673 - "Invalid exception code %d",  
674 - response[offset + 2]);  
675 - error_treat(mb_param, INVALID_EXCEPTION_CODE,  
676 - s_error);  
677 - free(s_error);  
678 - return INVALID_EXCEPTION_CODE; 662 + /* Check for exception response.
  663 + 0x80 + function is stored in the exception
  664 + response. */
  665 + if (0x80 + query[offset + 1] == response[offset + 1]) {
  666 +
  667 + int exception_code = response[offset + 2];
  668 + // FIXME check test
  669 + if (exception_code < NB_TAB_ERROR_MSG) {
  670 + error_treat(mb_param, -exception_code,
  671 + TAB_ERROR_MSG[response[offset + 2]]);
  672 + /* Modbus error code is negative */
  673 +
  674 + /* RETURN THE GOOD EXCEPTION CODE */
  675 + return -exception_code;
  676 + } else {
  677 + /* The chances are low to hit this
  678 + case but it can avoid a vicious
  679 + segfault */
  680 + char *s_error = malloc(64 * sizeof(char));
  681 + sprintf(s_error,
  682 + "Invalid exception code %d",
  683 + response[offset + 2]);
  684 + error_treat(mb_param, INVALID_EXCEPTION_CODE,
  685 + s_error);
  686 + free(s_error);
  687 + return INVALID_EXCEPTION_CODE;
  688 + }
679 } 689 }
  690 + /* If doesn't return previously, return as
  691 + TIME OUT here */
680 } 692 }
681 - } else if (ret == COMM_TIME_OUT) { 693 +
682 /* COMMUNICATION TIME OUT */ 694 /* COMMUNICATION TIME OUT */
683 error_treat(mb_param, ret, "Communication time out"); 695 error_treat(mb_param, ret, "Communication time out");
684 return ret; 696 return ret;
685 - } else {  
686 - /* OTHER */  
687 - return ret;  
688 } 697 }
689 698
690 - return response_length; 699 + return ret;
691 } 700 }
692 701
693 static int response_io_status(int address, int nb, 702 static int response_io_status(int address, int nb,
@@ -926,6 +935,7 @@ int modbus_listen(modbus_param_t *mb_param, uint8_t *query, int *query_length) @@ -926,6 +935,7 @@ int modbus_listen(modbus_param_t *mb_param, uint8_t *query, int *query_length)
926 { 935 {
927 int ret; 936 int ret;
928 937
  938 + /* The length of the query to receive isn't known. */
929 ret = receive_msg(mb_param, MSG_LENGTH_UNDEFINED, query, query_length); 939 ret = receive_msg(mb_param, MSG_LENGTH_UNDEFINED, query, query_length);
930 940
931 return ret; 941 return ret;