Commit 084e7e6a0fef23375eb85663457105f2cfdd1c9c
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; | ... | ... |