Commit c7a6ffb357dd0f31e0ab61f4462af2ee84f355db

Authored by Stéphane Raimbault
1 parent fe8d9de6

New slave able to manage many connections on uniprocessor architecture

- new functions modbus_slave_init_listen_tcp, modbus_slave_accept_tcp,
  modbus_slave_slave_receive.
- removed printf in modbus.c: 'Connection closed'
- new slave test, bandwith-slave-many-up
- updated build scripts
- updated MIGRATION document file
MIGRATION
  1 +=============================
  2 +Migration from the 2.0 series
  3 +=============================
  4 +
  5 +modbus_init_listen_tcp() has been renamed to modbus_slave_listen_tcp() and
  6 +requires a new argument, the maximal number of connections:
  7 +
  8 +int modbus_slave_init_tcp(modbus_param_t *mb_param, int nb_connection);
  9 +
  10 +
  11 +New function modbus_slave_accept_tcp() to etablish a new connection (previously
  12 +in modbus_init_listen_tcp()):
  13 +
  14 +int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket);
  15 +
  16 +
  17 +modbus_listen() has been renamed to modbus_slave_receive() and requires a new
  18 +argument, the socket file descriptor to listen on. If the sockfd is -1, the
  19 +internal fd of modbus_param_t is used:
  20 +
  21 +int modbus_slave_receive(modbus_param_t *mb_param, int sockfd,
  22 + uint8_t *query, int *query_length);
  23 +
  24 +
1 25 ===================================
2 26 Migration notes from the 1.2 series
3 27 ===================================
... ...
modbus/modbus.c
... ... @@ -498,7 +498,7 @@ static int receive_msg(modbus_param_t *mb_param,
498 498 tv.tv_usec = TIME_OUT_BEGIN_OF_TRAME;
499 499 state = COMPLETE;
500 500 }
501   -
  501 +
502 502 length_to_read = msg_length_computed;
503 503  
504 504 select_ret = 0;
... ... @@ -515,7 +515,6 @@ static int receive_msg(modbus_param_t *mb_param,
515 515 read_ret = recv(mb_param->fd, p_msg, length_to_read, 0);
516 516  
517 517 if (read_ret == 0) {
518   - printf("Connection closed\n");
519 518 return CONNECTION_CLOSED;
520 519 } else if (read_ret < 0) {
521 520 /* The only negative possible value is -1 */
... ... @@ -524,7 +523,7 @@ static int receive_msg(modbus_param_t *mb_param,
524 523 return PORT_SOCKET_FAILURE;
525 524 }
526 525  
527   - /* Sums bytes received */
  526 + /* Sums bytes received */
528 527 (*p_msg_length) += read_ret;
529 528  
530 529 /* Display the hex code of each character received */
... ... @@ -590,6 +589,28 @@ static int receive_msg(modbus_param_t *mb_param,
590 589 return 0;
591 590 }
592 591  
  592 +/* Listens for any query from a modbus master in TCP, requires the socket file
  593 + descriptor etablished with the master device in argument or -1 to use the
  594 + internal one of modbus_param_t.
  595 +
  596 + Returns:
  597 + - 0 if OK, or a negative error number if the request fails
  598 + - query, message received
  599 + - query_length, length in bytes of the message */
  600 +int modbus_slave_receive(modbus_param_t *mb_param, int sockfd,
  601 + uint8_t *query, int *query_length)
  602 +{
  603 + int ret;
  604 +
  605 + if (sockfd != -1) {
  606 + mb_param->fd = sockfd;
  607 + }
  608 +
  609 + /* The length of the query to receive isn't known. */
  610 + ret = receive_msg(mb_param, MSG_LENGTH_UNDEFINED, query, query_length);
  611 +
  612 + return ret;
  613 +}
593 614  
594 615 /* Receives the response and checks values (and checksum in RTU).
595 616  
... ... @@ -757,6 +778,7 @@ static int response_exception(modbus_param_t *mb_param, sft_t *sft,
757 778  
758 779 /* Manages the received query.
759 780 Analyses the query and constructs a response.
  781 +
760 782 If an error occurs, this function construct the response
761 783 accordingly.
762 784 */
... ... @@ -948,21 +970,6 @@ void modbus_manage_query(modbus_param_t *mb_param, const uint8_t *query,
948 970 modbus_send(mb_param, response, resp_length);
949 971 }
950 972  
951   -/* Listens any message on a socket or file descriptor.
952   - Returns:
953   - - 0 if OK, or a negative error number if the request fails
954   - - query, message received
955   - - query_length, length in bytes of the message */
956   -int modbus_listen(modbus_param_t *mb_param, uint8_t *query, int *query_length)
957   -{
958   - int ret;
959   -
960   - /* The length of the query to receive isn't known. */
961   - ret = receive_msg(mb_param, MSG_LENGTH_UNDEFINED, query, query_length);
962   -
963   - return ret;
964   -}
965   -
966 973 /* Reads IO status */
967 974 static int read_io_status(modbus_param_t *mb_param, int slave, int function,
968 975 int start_addr, int nb, uint8_t *data_dest)
... ... @@ -1628,10 +1635,6 @@ static int modbus_connect_tcp(modbus_param_t *mb_param)
1628 1635 int option;
1629 1636 struct sockaddr_in addr;
1630 1637  
1631   - addr.sin_family = AF_INET;
1632   - addr.sin_port = htons(mb_param->port);
1633   - addr.sin_addr.s_addr = inet_addr(mb_param->ip);
1634   -
1635 1638 mb_param->fd = socket(AF_INET, SOCK_STREAM, 0);
1636 1639 if (mb_param->fd < 0) {
1637 1640 return mb_param->fd;
... ... @@ -1661,7 +1664,10 @@ static int modbus_connect_tcp(modbus_param_t *mb_param)
1661 1664 if (mb_param->debug) {
1662 1665 printf("Connecting to %s\n", mb_param->ip);
1663 1666 }
1664   -
  1667 +
  1668 + addr.sin_family = AF_INET;
  1669 + addr.sin_port = htons(mb_param->port);
  1670 + addr.sin_addr.s_addr = inet_addr(mb_param->ip);
1665 1671 ret = connect(mb_param->fd, (struct sockaddr *)&addr,
1666 1672 sizeof(struct sockaddr_in));
1667 1673 if (ret < 0) {
... ... @@ -1784,60 +1790,64 @@ void modbus_mapping_free(modbus_mapping_t *mb_mapping)
1784 1790 free(mb_mapping->tab_input_registers);
1785 1791 }
1786 1792  
1787   -/* Listens for any query from a modbus master in TCP */
1788   -int modbus_init_listen_tcp(modbus_param_t *mb_param)
  1793 +/* Listens for any query from one or many modbus masters in TCP */
  1794 +int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection)
1789 1795 {
1790   - int ret;
1791 1796 int new_socket;
  1797 + int yes;
1792 1798 struct sockaddr_in addr;
1793   - socklen_t addrlen;
1794   -
1795   - addr.sin_family = AF_INET;
1796   - /* If the modbus port is < to 1024, we need the setuid root. */
1797   - addr.sin_port = htons(mb_param->port);
1798   - addr.sin_addr.s_addr = INADDR_ANY;
1799   - memset(&(addr.sin_zero), '\0', 8);
1800 1799  
1801 1800 new_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1802 1801 if (new_socket < 0) {
1803 1802 perror("socket");
1804   - exit(1);
1805   - } else {
1806   - printf("Socket OK\n");
  1803 + return -1;
1807 1804 }
1808 1805  
1809   - ret = bind(new_socket, (struct sockaddr *)&addr,
1810   - sizeof(struct sockaddr_in));
1811   - if (ret < 0) {
  1806 + yes = 1;
  1807 + if (setsockopt(new_socket, SOL_SOCKET, SO_REUSEADDR,
  1808 + (char *) &yes, sizeof(yes)) < 0) {
  1809 + perror("setsockopt");
  1810 + close(new_socket);
  1811 + return -1;
  1812 + }
  1813 +
  1814 + memset(&addr, 0, sizeof(addr));
  1815 + addr.sin_family = AF_INET;
  1816 + /* If the modbus port is < to 1024, we need the setuid root. */
  1817 + addr.sin_port = htons(mb_param->port);
  1818 + addr.sin_addr.s_addr = INADDR_ANY;
  1819 + if (bind(new_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1812 1820 perror("bind");
1813 1821 close(new_socket);
1814   - exit(1);
1815   - } else {
1816   - printf("Bind OK\n");
  1822 + return -1;
1817 1823 }
1818 1824  
1819   - ret = listen(new_socket, 1);
1820   - if (ret != 0) {
  1825 + if (listen(new_socket, nb_connection) < 0) {
1821 1826 perror("listen");
1822 1827 close(new_socket);
1823   - exit(1);
1824   - } else {
1825   - printf("Listen OK\n");
  1828 + return -1;
1826 1829 }
1827 1830  
  1831 + return new_socket;
  1832 +}
  1833 +
  1834 +int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket)
  1835 +{
  1836 + struct sockaddr_in addr;
  1837 + socklen_t addrlen;
  1838 +
1828 1839 addrlen = sizeof(struct sockaddr_in);
1829   - mb_param->fd = accept(new_socket, (struct sockaddr *)&addr, &addrlen);
  1840 + mb_param->fd = accept(*socket, (struct sockaddr *)&addr, &addrlen);
1830 1841 if (mb_param->fd < 0) {
1831 1842 perror("accept");
1832   - close(new_socket);
1833   - new_socket = 0;
1834   - exit(1);
  1843 + close(*socket);
  1844 + *socket = 0;
1835 1845 } else {
1836 1846 printf("The client %s is connected\n",
1837 1847 inet_ntoa(addr.sin_addr));
1838 1848 }
1839 1849  
1840   - return new_socket;
  1850 + return mb_param->fd;
1841 1851 }
1842 1852  
1843 1853 /** Utils **/
... ...
modbus/modbus.h
... ... @@ -279,12 +279,25 @@ int modbus_mapping_new(modbus_mapping_t *mb_mapping,
279 279 /* Frees the 4 arrays */
280 280 void modbus_mapping_free(modbus_mapping_t *mb_mapping);
281 281  
282   -/* Initializes the modbus_param_t structure for a TCP slave (server) */
283   -int modbus_init_listen_tcp(modbus_param_t *mb_param);
  282 +/* Listens for any query from one or many modbus masters in TCP.
284 283  
285   -/* Listens for any query from a modbus master in TCP
286   - Not tested in RTU communication. */
287   -int modbus_listen(modbus_param_t *mb_param, uint8_t *query, int *query_length);
  284 + Returns: socket
  285 + */
  286 +int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection);
  287 +
  288 +/* Waits for a connection */
  289 +int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket);
  290 +
  291 +/* Listens for any query from a modbus master in TCP, requires the socket file
  292 + descriptor etablished with the master device in argument.
  293 +
  294 + Returns:
  295 + - 0 if OK, or a negative error number if the request fails
  296 + - query, message received
  297 + - query_length, length in bytes of the message
  298 +*/
  299 +int modbus_slave_receive(modbus_param_t *mb_param, int sockfd,
  300 + uint8_t *query, int *query_length);
288 301  
289 302 /* Manages the received query.
290 303 Analyses the query and constructs a response.
... ...
tests/Makefile.am
... ... @@ -5,8 +5,9 @@ noinst_PROGRAMS = \
5 5 random-test-master \
6 6 unit-test-slave \
7 7 unit-test-master \
8   - bench-bandwidth-slave \
9   - bench-bandwidth-master
  8 + bandwidth-slave-one \
  9 + bandwidth-slave-many-up \
  10 + bandwidth-master
10 11  
11 12 common_ldflags = \
12 13 $(top_builddir)/modbus/libmodbus.la
... ... @@ -23,11 +24,14 @@ unit_test_slave_LDADD = $(common_ldflags)
23 24 unit_test_master_SOURCES = unit-test-master.c unit-test.h
24 25 unit_test_master_LDADD = $(common_ldflags)
25 26  
26   -bench_bandwidth_slave_SOURCES = bench-bandwidth-slave.c
27   -bench_bandwidth_slave_LDADD = $(common_ldflags)
  27 +bandwidth_slave_one_SOURCES = bandwidth-slave-one.c
  28 +bandwidth_slave_one_LDADD = $(common_ldflags)
28 29  
29   -bench_bandwidth_master_SOURCES = bench-bandwidth-master.c
30   -bench_bandwidth_master_LDADD = $(common_ldflags)
  30 +bandwidth_slave_many_up_SOURCES = bandwidth-slave-many-up.c
  31 +bandwidth_slave_many_up_LDADD = $(common_ldflags)
  32 +
  33 +bandwidth_master_SOURCES = bandwidth-master.c
  34 +bandwidth_master_LDADD = $(common_ldflags)
31 35  
32 36 INCLUDES = -I$(top_srcdir)
33 37 CLEANFILES = *~
... ...
tests/bench-bandwidth-master.c renamed to tests/bandwidth-master.c
... ... @@ -33,7 +33,7 @@ uint32_t gettime(void)
33 33 {
34 34 struct timeval tv;
35 35 gettimeofday (&tv, NULL);
36   -
  36 +
37 37 return (uint32_t) tv.tv_sec * G_USEC_PER_SEC + tv.tv_usec;
38 38 }
39 39  
... ... @@ -61,7 +61,7 @@ int main(void)
61 61 /* Allocate and initialize the memory to store the status */
62 62 tab_rp_status = (uint8_t *) malloc(MAX_STATUS * sizeof(uint8_t));
63 63 memset(tab_rp_status, 0, MAX_STATUS * sizeof(uint8_t));
64   -
  64 +
65 65 /* Allocate and initialize the memory to store the registers */
66 66 tab_rp_registers = (uint16_t *) malloc(MAX_REGISTERS * sizeof(uint16_t));
67 67 memset(tab_rp_registers, 0, MAX_REGISTERS * sizeof(uint16_t));
... ... @@ -78,7 +78,7 @@ int main(void)
78 78  
79 79 rate = (NB_LOOPS * nb_points) * G_USEC_PER_SEC / (end - start);
80 80 printf("Transfert rate in points/seconds:\n");
81   - printf("* %'d points/s\n", rate);
  81 + printf("* %'d points/s\n", rate);
82 82 printf("\n");
83 83  
84 84 bytes = NB_LOOPS * (nb_points / 8) + ((nb_points % 8) ? 1 : 0);
... ... @@ -88,7 +88,7 @@ int main(void)
88 88 printf("* %.3f ms for %d bytes\n", elapsed, bytes);
89 89 printf("* %'d KiB/s\n", rate);
90 90 printf("\n");
91   -
  91 +
92 92 /* TCP: Query and reponse header and values */
93 93 bytes = 12 + 9 + (nb_points / 8) + ((nb_points % 8) ? 1 : 0);
94 94 printf("Values and TCP Modbus overhead:\n");
... ... @@ -111,7 +111,7 @@ int main(void)
111 111  
112 112 rate = (NB_LOOPS * nb_points) * G_USEC_PER_SEC / (end - start);
113 113 printf("Transfert rate in points/seconds:\n");
114   - printf("* %'d registers/s\n", rate);
  114 + printf("* %'d registers/s\n", rate);
115 115 printf("\n");
116 116  
117 117 bytes = NB_LOOPS * nb_points * sizeof(uint16_t);
... ... @@ -121,7 +121,7 @@ int main(void)
121 121 printf("* %.3f ms for %d bytes\n", elapsed, bytes);
122 122 printf("* %'d KiB/s\n", rate);
123 123 printf("\n");
124   -
  124 +
125 125 /* TCP:Query and reponse header and values */
126 126 bytes = 12 + 9 + (nb_points * sizeof(uint16_t));
127 127 printf("Values and TCP Modbus overhead:\n");
... ... @@ -133,11 +133,11 @@ int main(void)
133 133 printf("\n");
134 134  
135 135 /* Free the memory */
136   - free(tab_rp_status);
  136 + free(tab_rp_status);
137 137 free(tab_rp_registers);
138 138  
139 139 /* Close the connection */
140 140 modbus_close(&mb_param);
141   -
  141 +
142 142 return 0;
143 143 }
... ...
tests/bandwidth-slave-many-up.c 0 → 100644
  1 +/*
  2 + * Copyright © 2009 Stéphane Raimbault <stephane.raimbault@gmail.com>
  3 + *
  4 + * This program is free software: you can redistribute it and/or modify
  5 + * it under the terms of the GNU General Public License as published by
  6 + * the Free Software Foundation; either version 3 of the License, or
  7 + * (at your option) any later version.
  8 + *
  9 + * This program is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + * GNU General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU General Public License
  15 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16 + */
  17 +
  18 +#include <stdio.h>
  19 +#include <unistd.h>
  20 +#include <string.h>
  21 +#include <stdlib.h>
  22 +#include <errno.h>
  23 +#include <signal.h>
  24 +
  25 +#include <modbus/modbus.h>
  26 +
  27 +#define NB_CONNECTION 5
  28 +int slave_socket;
  29 +modbus_mapping_t mb_mapping;
  30 +
  31 +static void close_sigint(int dummy)
  32 +{
  33 + shutdown(slave_socket, SHUT_RDWR);
  34 + close(slave_socket);
  35 + modbus_mapping_free(&mb_mapping);
  36 +
  37 + exit(dummy);
  38 +}
  39 +
  40 +int main(void)
  41 +{
  42 + int master_socket;
  43 + modbus_param_t mb_param;
  44 + int ret;
  45 + fd_set refset;
  46 + fd_set rdset;
  47 +
  48 + /* Maximum file descriptor number */
  49 + int fdmax;
  50 +
  51 + modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
  52 +
  53 + ret = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0);
  54 + if (ret == FALSE) {
  55 + printf("Memory allocation failure\n");
  56 + exit(1);
  57 + }
  58 +
  59 + slave_socket = modbus_slave_listen_tcp(&mb_param, NB_CONNECTION);
  60 +
  61 + signal(SIGINT, close_sigint);
  62 +
  63 + /* Clear the reference set of socket */
  64 + FD_ZERO(&refset);
  65 + /* Add the slave socket */
  66 + FD_SET(slave_socket, &refset);
  67 +
  68 + /* Keep track of the max file descriptor */
  69 + fdmax = slave_socket;
  70 +
  71 + for (;;) {
  72 + rdset = refset;
  73 + if (select(fdmax+1, &rdset, NULL, NULL, NULL) == -1) {
  74 + perror("Slave select() failure.");
  75 + close_sigint(1);
  76 + }
  77 +
  78 + /* Run through the existing connections looking for data to be
  79 + * read */
  80 + for (master_socket = 0; master_socket <= fdmax; master_socket++) {
  81 +
  82 + if (FD_ISSET(master_socket, &rdset)) {
  83 + if (master_socket == slave_socket) {
  84 + /* A client is asking a new connection */
  85 + socklen_t addrlen;
  86 + struct sockaddr_in clientaddr;
  87 + int newfd;
  88 +
  89 + /* Handle new connections */
  90 + addrlen = sizeof(clientaddr);
  91 + memset(&clientaddr, 0, sizeof(clientaddr));
  92 + newfd = accept(slave_socket, (struct sockaddr *)&clientaddr, &addrlen);
  93 + if (newfd == -1) {
  94 + perror("Server accept() error");
  95 + } else {
  96 + FD_SET(newfd, &refset);
  97 +
  98 + if (newfd > fdmax) {
  99 + /* Keep track of the maximum */
  100 + fdmax = newfd;
  101 + }
  102 + printf("New connection from %s:%d on socket %d\n",
  103 + inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port, newfd);
  104 + }
  105 + } else {
  106 + /* An already connected master has sent a new query */
  107 + uint8_t query[MAX_MESSAGE_LENGTH];
  108 + int query_size;
  109 +
  110 + ret = modbus_slave_receive(&mb_param, master_socket, query, &query_size);
  111 + if (ret == 0) {
  112 + modbus_manage_query(&mb_param, query, query_size, &mb_mapping);
  113 + } else {
  114 + /* Connection closed by the client, end of server */
  115 + printf("Connection closed on socket %d\n", master_socket);
  116 + shutdown(master_socket, SHUT_RDWR);
  117 + close(master_socket);
  118 +
  119 + /* Remove from reference set */
  120 + FD_CLR(master_socket, &refset);
  121 +
  122 + if (master_socket == fdmax) {
  123 + fdmax--;
  124 + }
  125 + }
  126 + }
  127 + }
  128 + }
  129 + }
  130 +
  131 + return 0;
  132 +}
... ...
tests/bench-bandwidth-slave.c renamed to tests/bandwidth-slave-one.c
... ... @@ -37,13 +37,14 @@ int main(void)
37 37 exit(1);
38 38 }
39 39  
40   - socket = modbus_init_listen_tcp(&mb_param);
41   -
  40 + socket = modbus_slave_listen_tcp(&mb_param, 1);
  41 + modbus_slave_accept_tcp(&mb_param, &socket);
  42 +
42 43 while (1) {
43 44 uint8_t query[MAX_MESSAGE_LENGTH];
44 45 int query_size;
45 46  
46   - ret = modbus_listen(&mb_param, query, &query_size);
  47 + ret = modbus_slave_receive(&mb_param, -1, query, &query_size);
47 48 if (ret == 0) {
48 49 modbus_manage_query(&mb_param, query, query_size, &mb_mapping);
49 50 } else if (ret == CONNECTION_CLOSED) {
... ...
tests/random-test-slave.c
... ... @@ -37,13 +37,14 @@ int main(void)
37 37 exit(1);
38 38 }
39 39  
40   - socket = modbus_init_listen_tcp(&mb_param);
41   -
  40 + socket = modbus_slave_listen_tcp(&mb_param, 1);
  41 + modbus_slave_accept_tcp(&mb_param, &socket);
  42 +
42 43 while (1) {
43 44 uint8_t query[MAX_MESSAGE_LENGTH];
44 45 int query_size;
45 46  
46   - ret = modbus_listen(&mb_param, query, &query_size);
  47 + ret = modbus_slave_receive(&mb_param, -1, query, &query_size);
47 48 if (ret == 0) {
48 49 modbus_manage_query(&mb_param, query, query_size, &mb_mapping);
49 50 } else if (ret == CONNECTION_CLOSED) {
... ...
tests/unit-test-slave.c
... ... @@ -59,13 +59,14 @@ int main(void)
59 59 UT_INPUT_REGISTERS_TAB[i];;
60 60 }
61 61  
62   - socket = modbus_init_listen_tcp(&mb_param);
63   -
  62 + socket = modbus_slave_listen_tcp(&mb_param, 1);
  63 + modbus_slave_accept_tcp(&mb_param, &socket);
  64 +
64 65 while (1) {
65 66 uint8_t query[MAX_MESSAGE_LENGTH];
66 67 int query_size;
67 68  
68   - ret = modbus_listen(&mb_param, query, &query_size);
  69 + ret = modbus_slave_receive(&mb_param, -1, query, &query_size);
69 70 if (ret == 0) {
70 71 if (((query[HEADER_LENGTH_TCP + 4] << 8) + query[HEADER_LENGTH_TCP + 5])
71 72 == UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL) {
... ...
tests/wscript
... ... @@ -28,15 +28,22 @@ def build(bld):
28 28 obj.inst_var = 0
29 29  
30 30 obj = bld.create_obj('cc', 'program')
31   - obj.source = 'bench-bandwidth-slave.c'
  31 + obj.source = 'bandwidth-slave-one.c'
32 32 obj.includes = '. ..'
33 33 obj.uselib_local = 'modbus'
34   - obj.target = 'bench-bandwidth-slave'
  34 + obj.target = 'bandwidth-slave-one'
35 35 obj.inst_var = 0
36 36  
37 37 obj = bld.create_obj('cc', 'program')
38   - obj.source = 'bench-bandwidth-master.c'
  38 + obj.source = 'bandwidth-slave-many-up.c'
39 39 obj.includes = '. ..'
40 40 obj.uselib_local = 'modbus'
41   - obj.target = 'bench-bandwidth-master'
  41 + obj.target = 'bandwidth-slave-many-up'
  42 + obj.inst_var = 0
  43 +
  44 + obj = bld.create_obj('cc', 'program')
  45 + obj.source = 'bandwidth-master.c'
  46 + obj.includes = '. ..'
  47 + obj.uselib_local = 'modbus'
  48 + obj.target = 'bandwidth-master'
42 49 obj.inst_var = 0
... ...