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 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 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 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 466 int select_ret;
463 467 int read_ret;
... ... @@ -502,8 +506,8 @@ int receive_msg(modbus_param_t *mb_param,
502 506 select_ret = 0;
503 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 511 p_msg = msg;
508 512  
509 513 while (select_ret) {
... ... @@ -523,7 +527,7 @@ int receive_msg(modbus_param_t *mb_param,
523 527 }
524 528  
525 529 /* Sums bytes received */
526   - (*msg_length) += read_ret;
  530 + (*p_msg_length) += read_ret;
527 531  
528 532 /* Display the hex code of each character received */
529 533 if (mb_param->debug) {
... ... @@ -532,9 +536,9 @@ int receive_msg(modbus_param_t *mb_param,
532 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 540 /* Message incomplete */
537   - length_to_read = msg_length_computed - (*msg_length);
  541 + length_to_read = msg_length_computed - (*p_msg_length);
538 542 } else {
539 543 switch (state) {
540 544 case FUNCTION:
... ... @@ -542,7 +546,7 @@ int receive_msg(modbus_param_t *mb_param,
542 546 length_to_read = compute_query_length_header(msg[mb_param->header_length + 1]);
543 547 msg_length_computed += length_to_read;
544 548 /* It's useless to check
545   - msg_length_computed value in this
  549 + p_msg_length_computed value in this
546 550 case (only defined values are used). */
547 551 state = BYTE;
548 552 break;
... ... @@ -581,7 +585,7 @@ int receive_msg(modbus_param_t *mb_param,
581 585 printf("\n");
582 586  
583 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 591 /* OK */
... ... @@ -592,7 +596,8 @@ int receive_msg(modbus_param_t *mb_param,
592 596 /* Receives the response and checks values (and checksum in RTU).
593 597  
594 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 601 - less than 0 for exception errors
597 602  
598 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 606 uint8_t *query,
602 607 uint8_t *response)
603 608 {
  609 + int ret;
604 610 int response_length;
605   - int response_length_computed;
  611 + int response_length_computed;
606 612 int offset = mb_param->header_length;
607   - int ret;
608 613  
609 614 response_length_computed = compute_response_length(mb_param, query);
610 615 ret = receive_msg(mb_param, response_length_computed,
... ... @@ -612,21 +617,23 @@ static int modbus_receive(modbus_param_t *mb_param,
612 617 if (ret == 0) {
613 618 /* GOOD RESPONSE */
614 619  
  620 + /* The number of values is returned for the following
  621 + * cases */
615 622 switch (response[offset + 1]) {
616 623 case FC_READ_COIL_STATUS:
617 624 case FC_READ_INPUT_STATUS:
618 625 /* Read functions 1 value = 1 byte */
619   - response_length = response[offset + 2];
  626 + ret = response[offset + 2];
620 627 break;
621 628 case FC_READ_HOLDING_REGISTERS:
622 629 case FC_READ_INPUT_REGISTERS:
623 630 /* Read functions 1 value = 2 bytes */
624   - response_length = response[offset + 2] / 2;
  631 + ret = response[offset + 2] / 2;
625 632 break;
626 633 case FC_FORCE_MULTIPLE_COILS:
627 634 case FC_PRESET_MULTIPLE_REGISTERS:
628 635 /* N Write functions */
629   - response_length = response[offset + 4] << 8 |
  636 + ret = response[offset + 4] << 8 |
630 637 response[offset + 5];
631 638 break;
632 639 case FC_REPORT_SLAVE_ID:
... ... @@ -634,60 +641,62 @@ static int modbus_receive(modbus_param_t *mb_param,
634 641 break;
635 642 default:
636 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 694 /* COMMUNICATION TIME OUT */
683 695 error_treat(mb_param, ret, "Communication time out");
684 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 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 935 {
927 936 int ret;
928 937  
  938 + /* The length of the query to receive isn't known. */
929 939 ret = receive_msg(mb_param, MSG_LENGTH_UNDEFINED, query, query_length);
930 940  
931 941 return ret;
... ...