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,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; |