├── .gitignore
├── NET_API
├── inc
│ ├── arp.h
│ ├── dhcp.h
│ ├── ethernet.h
│ ├── icmp.h
│ ├── ipv4.h
│ ├── network_utilities.h
│ ├── tcp.h
│ └── udp.h
└── src
│ ├── arp.c
│ ├── dhcp.c
│ ├── ethernet.c
│ ├── icmp.c
│ ├── ipv4.c
│ ├── network_utilities.c
│ ├── tcp.c
│ └── udp.c
├── README.md
├── enc28j60.c
├── enc28j60.h
├── main.c
├── tm4c123gh6pm.h
├── tm4c123gh6pm_startup_ccs.c
├── wait.c
└── wait.h
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | Debug
3 |
4 | targetConfigs
5 |
6 | *.cmd
7 |
8 | .ccsproject
9 | .cproject
10 | .launches
11 | .project
12 | .settings
13 |
--------------------------------------------------------------------------------
/NET_API/inc/arp.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file arp.h
4 | * @author Aditya Mall,
5 | * @brief arp protocol header file
6 | *
7 | * Info
8 | *
9 | ******************************************************************************
10 | * @attention
11 | *
12 | *
© COPYRIGHT(c) 2019 Aditya Mall, MIT License
13 | *
14 | * MIT License
15 | *
16 | * Copyright (c) 2019 Aditya Mall
17 | *
18 | * Permission is hereby granted, free of charge, to any person obtaining a copy
19 | * of this software and associated documentation files (the "Software"), to deal
20 | * in the Software without restriction, including without limitation the rights
21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | * copies of the Software, and to permit persons to whom the Software is
23 | * furnished to do so, subject to the following conditions:
24 | *
25 | * The above copyright notice and this permission notice shall be included in all
26 | * copies or substantial portions of the Software.
27 | *
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | ******************************************************************************
40 | */
41 |
42 | #ifndef ARP_H_
43 | #define ARP_H_
44 |
45 |
46 | /*
47 | * Standard header and api header files
48 | */
49 | #include
50 |
51 | #include "ethernet.h"
52 |
53 |
54 |
55 | /******************************************************************************/
56 | /* */
57 | /* Defines */
58 | /* */
59 | /******************************************************************************/
60 |
61 | /* Used by other protocols to resolve address */
62 | #define ARP_FRAME_SIZE 28
63 |
64 |
65 |
66 |
67 | /******************************************************************************/
68 | /* */
69 | /* ARP Function Prototypes */
70 | /* */
71 | /******************************************************************************/
72 |
73 |
74 | /********************************************************
75 | * @brief Function to send arp request
76 | * @param *ethernet : reference to the Ethernet handle
77 | * @param *sender_ip : sender ip address
78 | * @param *target_ip : target ip address
79 | * @retval int16_t : Error = -1, Success = 0
80 | ********************************************************/
81 | int16_t ether_send_arp_req(ethernet_handle_t *ethernet, uint8_t *sender_ip, uint8_t *target_ip);
82 |
83 |
84 |
85 | /**********************************************************
86 | * @brief Function to independently read ARP data
87 | * (Blocking Call)
88 | * @param *ethernet : reference to the Ethernet handle
89 | * @param *data : network_data
90 | * @param *data_length : length of data to be read
91 | * @retval uint8_t : Error = 0, Success = 1
92 | **********************************************************/
93 | uint8_t ether_is_arp(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length);
94 |
95 |
96 |
97 | /******************************************************************
98 | * @brief Function to handle ARP request and reply
99 | * sends ARP reply if ARP request received
100 | * @param *ethernet : reference to the Ethernet handle
101 | * @retval int16_t : Error = -2, -3 = reply ignore, Success = 0
102 | ******************************************************************/
103 | int16_t ether_handle_arp_resp_req(ethernet_handle_t *ethernet);
104 |
105 |
106 |
107 |
108 | /***********************************************************************
109 | * @brief Function to get MAC address from destination IP address
110 | * by searching local ARP table
111 | * @param *ethernet : reference to the Ethernet handle
112 | * @param *mac_address : device mac_address
113 | * @param *ip_address : device ip address
114 | * @retval int8_t : Success = 1 device found else 0 for not found
115 | ***********************************************************************/
116 | uint8_t ether_arp_resolve_address(ethernet_handle_t *ethernet, uint8_t *destination_mac, uint8_t *destination_ip);
117 |
118 |
119 |
120 |
121 | #endif /* ARP_H_ */
122 |
--------------------------------------------------------------------------------
/NET_API/inc/dhcp.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file dhcp.h
4 | * @author Aditya Mall,
5 | * @brief DHCP protocol header file
6 | *
7 | * Info
8 | *
9 | ******************************************************************************
10 | * @attention
11 | *
12 | * © COPYRIGHT(c) 2019 Aditya Mall, MIT License
13 | *
14 | * MIT License
15 | *
16 | * Copyright (c) 2019 Aditya Mall
17 | *
18 | * Permission is hereby granted, free of charge, to any person obtaining a copy
19 | * of this software and associated documentation files (the "Software"), to deal
20 | * in the Software without restriction, including without limitation the rights
21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | * copies of the Software, and to permit persons to whom the Software is
23 | * furnished to do so, subject to the following conditions:
24 | *
25 | * The above copyright notice and this permission notice shall be included in all
26 | * copies or substantial portions of the Software.
27 | *
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | ******************************************************************************
40 | */
41 |
42 | #ifndef DHCP_H_
43 | #define DHCP_H_
44 |
45 |
46 |
47 | /*
48 | * Standard header and api header files
49 | */
50 | #include
51 |
52 | #include "ethernet.h"
53 |
54 |
55 |
56 | /******************************************************************************/
57 | /* */
58 | /* Data Structures and Defines */
59 | /* */
60 | /******************************************************************************/
61 |
62 |
63 |
64 |
65 | /* DHCP states */
66 | typedef enum _dhcp_state_values
67 | {
68 | DHCP_INIT_STATE = 1,
69 | DHCP_SELECTING_STATE = 2,
70 | DHCP_READ_STATE = 3,
71 | DHCP_REQUESTING_STATE = 4,
72 | DHCP_ACK_STATE = 5,
73 | DHCP_BOUND_STATE = 6,
74 |
75 | }dhcp_states;
76 |
77 |
78 |
79 |
80 | /******************************************************************************/
81 | /* */
82 | /* DHCP Functions Prototypes */
83 | /* */
84 | /******************************************************************************/
85 |
86 |
87 |
88 | /**************************************************************
89 | * @brief Function Send DHCP Discover
90 | * @param *ethernet : reference to the Ethernet handle
91 | * @param transaction_id : random transaction ID
92 | *
93 | * @param seconds_elapsed : number of seconds elapsed
94 | * @retval uint8_t : Error = -1, Success = 0
95 | **************************************************************/
96 | int8_t ether_dhcp_send_discover(ethernet_handle_t *ethernet, uint32_t transaction_id, uint8_t *mac_address,
97 | uint16_t seconds_elapsed);
98 |
99 |
100 |
101 |
102 | /************************************************************
103 | * @brief Function read DHCP offer
104 | * @param *ethernet : reference to the Ethernet handle
105 | * @param *network_data : network_data from PHY
106 | * @param *your_ip : 'your IP' address
107 | *
108 | * @param *dhcp_options : DHCP options data
109 | * @retval uint8_t : Error = 0, Success = DHCP type
110 | ************************************************************/
111 | int8_t ether_dhcp_read(ethernet_handle_t *ethernet, uint8_t *network_data, uint8_t *your_ip, uint32_t client_transac_id, uint8_t *dhcp_options);
112 |
113 |
114 |
115 |
116 | /************************************************************
117 | * @brief Function read DHCP offer (Depreciated)
118 | * @param *ethernet : reference to the Ethernet handle
119 | * @param *network_data : network_data from PHY
120 | * @param *your_ip : 'your IP' address
121 | * @param *server_ip : server IP address
122 | * @param *subnet_mask : SUBNET mask
123 | * @param *lease_time : IP address lease time
124 | * @retval uint8_t : Error = 0, Success = 1
125 | ************************************************************/
126 | int8_t ether_dhcp_read_offer(ethernet_handle_t *ethernet, uint8_t *network_data, uint8_t *your_ip, uint8_t *server_ip,
127 | uint8_t *subnet_mask, uint8_t *lease_time);
128 |
129 |
130 |
131 |
132 | /*************************************************************
133 | * @brief Function Send DHCP Request
134 | * @param *ethernet : reference to the Ethernet handle
135 | * @param transaction_id : random transaction ID
136 | * @param seconds_elapsed : number of seconds elapsed
137 | * @param *server_ip : DHCP server IP
138 | * @param *requested_ip : IP request to the server
139 | * @param *lease_time : Lease time
140 | * @retval uint8_t : Error = -1, Success = 0
141 | *************************************************************/
142 | int8_t ether_dhcp_send_request(ethernet_handle_t *ethernet, uint32_t transaction_id, uint16_t seconds_elapsed,
143 | uint8_t *server_ip, uint8_t *requested_ip, uint32_t lease_time);
144 |
145 |
146 |
147 |
148 | /*************************************************************
149 | * @brief Function to get IP though DHCP state machine
150 | * @param *ethernet : reference to the Ethernet handle
151 | * @param *network_data : network data from PHY
152 | *
153 | * @param dhcp_state : DHCP state machine states
154 | * @retval uint8_t : Error = NA, Success = NA
155 | *************************************************************/
156 | int8_t ether_get_dhcp_ip(ethernet_handle_t *ethernet, uint8_t *network_data, uint8_t *mac_address,
157 | dhcp_states dhcp_state);
158 |
159 |
160 |
161 |
162 | #endif /* DHCP_H_ */
163 |
--------------------------------------------------------------------------------
/NET_API/inc/ethernet.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file ethernet.h
4 | * @author Aditya Mall,
5 | * @brief ethernet layer header file
6 | *
7 | * Info
8 | *
9 | ******************************************************************************
10 | * @attention
11 | *
12 | * © COPYRIGHT(c) 2019 Aditya Mall, MIT License
13 | *
14 | * MIT License
15 | *
16 | * Copyright (c) 2019 Aditya Mall
17 | *
18 | * Permission is hereby granted, free of charge, to any person obtaining a copy
19 | * of this software and associated documentation files (the "Software"), to deal
20 | * in the Software without restriction, including without limitation the rights
21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | * copies of the Software, and to permit persons to whom the Software is
23 | * furnished to do so, subject to the following conditions:
24 | *
25 | * The above copyright notice and this permission notice shall be included in all
26 | * copies or substantial portions of the Software.
27 | *
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | ******************************************************************************
40 | */
41 |
42 | #ifndef ETHERNET_H_
43 | #define ETHERNET_H_
44 |
45 |
46 |
47 | /*
48 | * Standard header and api header files
49 | */
50 | #include
51 |
52 |
53 |
54 | /******************************************************************************/
55 | /* */
56 | /* Macros and Defines */
57 | /* */
58 | /******************************************************************************/
59 |
60 | /* structure padding */
61 | #define pragma pack(1)
62 |
63 |
64 | #define ETHER_PHY_DATA_OFFSET 4
65 |
66 | #define ETHER_MAC_SIZE 6 /*!< Size of MAC address */
67 | #define ETHER_FRAME_SIZE 14 /*!< Ethernet Frame size */
68 | #define ETHER_IPV4_SIZE 4 /*!< IP protocol version 4 size */
69 | #define ARP_TABLE_SIZE 5 /*!< ARP Table size define */
70 | #define ETHER_MTU_SIZE 1460 /*!< MAX MTU size */
71 | #define APP_BUFF_SIZE 500 /*!< Application buffer size */
72 |
73 |
74 | /* Function define for random number generator function */
75 | #define get_unique_id get_random_port
76 | #define get_unique_id_l get_random_port_l
77 |
78 |
79 | /******************************************************************************/
80 | /* */
81 | /* Data Structures */
82 | /* */
83 | /******************************************************************************/
84 |
85 |
86 |
87 | /* Ethernet Frame structure (14 Bytes) */
88 | typedef struct _ether_frame
89 | {
90 | uint8_t destination_mac_addr[6]; /*!< Destination MAC address */
91 | uint8_t source_mac_addr[6]; /*!< Source MAC address */
92 | uint16_t type; /*!< Ethernet frame type */
93 | uint8_t data; /*!< Ethernet data/payload */
94 |
95 | }ether_frame_t;
96 |
97 |
98 |
99 | /* Ethernet Handle type defined */
100 | typedef struct _ethernet_handle ethernet_handle_t;
101 |
102 |
103 | /* ARP Table */
104 | typedef struct _arp_table
105 | {
106 | uint8_t ip_address[ETHER_IPV4_SIZE]; /*!< Device IP address */
107 | uint8_t mac_address[ETHER_MAC_SIZE]; /*!< Device MAC address */
108 |
109 | }arp_table_t;
110 |
111 |
112 | /* */
113 | typedef struct _network_timer_operations
114 | {
115 | uint8_t (*open)(void);
116 | uint8_t (*start)(uint8_t timer_type, uint32_t seconds);
117 | uint8_t (*stop)(void);
118 | uint8_t (*reset)(void);
119 |
120 | }net_timer_ops_t;
121 |
122 |
123 | /* Ethernet/Network Operations handle */
124 | typedef struct _ethernet_operations
125 | {
126 | uint8_t function_lock; /*!< Function Lock for exclusive access of functions (experimental ) */
127 | uint8_t (*open)(uint8_t *mac_address); /*!< Function initialize network/ETHER PHY, takes MAC address as parameter */
128 | uint8_t (*network_interface_status)(void); /*!< Network / Ethernet module packet receive status / trigger */
129 | uint16_t (*random_gen_seed)(void); /*!< Seed value return function for random number generation */
130 | int16_t (*ether_send_packet)(uint8_t *data, uint16_t length); /*!< Callback function to send Ethernet packet */
131 | uint16_t (*ether_recv_packet)(uint8_t *data, uint16_t length); /*!< Callback function to receive Ethernet packet */
132 |
133 | }ether_operations_t;
134 |
135 |
136 | /* Ethernet status fields */
137 | typedef struct _network_status
138 | {
139 | uint8_t mode_static : 1;
140 | uint8_t mode_dynamic : 1;
141 | uint8_t mode_dhcp_init : 1;
142 | uint8_t mode_dhcp_bound : 1;
143 | uint8_t mode_read_blocking : 1;
144 | uint8_t net_app_data_rdy : 1;
145 | uint8_t reserved : 2;
146 |
147 | }net_status_t;
148 |
149 |
150 |
151 | /* Ethernet/Network Handle */
152 | struct _ethernet_handle
153 | {
154 | ether_frame_t *ether_obj; /*!< Ethernet frame object */
155 | net_status_t status; /*!< Ethernet status fields */
156 | ether_operations_t *ether_commands; /*!< Network Operations */
157 | arp_table_t arp_table[ARP_TABLE_SIZE]; /*!< ARP Table */
158 |
159 | uint16_t ip_identifier; /*!< */
160 | uint16_t source_port; /*!< Ethernet source port, gets random source port value */
161 | char *net_application_data; /*!< Network application data, allocated by create handle */
162 | uint16_t net_app_data_length; /*!< */
163 | uint8_t host_mac[ETHER_MAC_SIZE]; /*!< Host MAC address, given by handle */
164 | uint8_t host_ip[ETHER_IPV4_SIZE]; /*!< Host IP address, static or dynamic */
165 | uint8_t broadcast_mac[ETHER_MAC_SIZE]; /*!< Broadcast MAC address */
166 | uint8_t broadcast_ip[ETHER_IPV4_SIZE]; /*!< Broadcast IP address */
167 | uint8_t subnet_mask[ETHER_IPV4_SIZE]; /*!< SUBNET mask, gets value from DHCP sever */
168 | uint8_t gateway_ip[ETHER_IPV4_SIZE]; /*!< Gateway or DHCP Server IP, from DHCP server */
169 | uint32_t lease_time; /*!< IP lease time, from DHCP server */
170 |
171 | };
172 |
173 |
174 | /**/
175 | typedef enum _ether_control_modes
176 | {
177 | ETHER_READ_NONBLOCK = 0,
178 | ETHER_READ_BLOCK = 1,
179 | ETHER_IP_STATIC = 2,
180 | ETHER_IP_DYNAMIC = 3,
181 |
182 | }ether_control_t;
183 |
184 |
185 |
186 | /* Ethernet source address fields, used for raw transport layer protocol functions */
187 | typedef struct _ethernet_source_addr
188 | {
189 | uint8_t source_mac[ETHER_MAC_SIZE]; /*!< Source MAC address */
190 | uint8_t source_ip[ETHER_IPV4_SIZE]; /*!< Source IP address */
191 | uint16_t source_port; /*!< Source port */
192 | uint16_t identifier; /*!< Protocol Message ID */
193 |
194 | }ether_source_t;
195 |
196 |
197 |
198 | /* Ethernet type values */
199 | typedef enum _ether_type
200 | {
201 | ETHER_IPV4 = 0x0800, /*!< IP protocol version 4 Ethernet type value */
202 | ETHER_ARP = 0x0806, /*!< ARP protocol Ethernet type value */
203 | ETHER_RARP = 0x8035, /*!< RARP protocol Ethernet type value */
204 |
205 | }ether_type_t;
206 |
207 |
208 |
209 | /* Network error codes protocol functions */
210 | typedef enum _network_error_codes
211 | {
212 | NET_ARP_REQ_ERROR = -1, /*!< */
213 | NET_ARP_RESP_ERROR = -2, /*!< */
214 | NET_ARP_RESP_IGNORE = -3, /*!< */
215 | NET_IP_GET_ERROR = -4, /*!< */
216 | NET_IP_CHECKSUM_ERROR = -5, /*!< */
217 | NET_ICMP_RESP_ERROR = -6, /*!< */
218 | NET_ICMP_RESP_IGNORE = -7, /*!< */
219 | NET_ICMP_REQ_ERROR = -8, /*!< */
220 | NET_UDP_RAW_SEND_ERROR = -9, /*!< */
221 | NET_UDP_SEND_ERROR = -10, /*!< */
222 | NET_TCP_CONNECT_ERROR = -11, /*!< */
223 | NET_TCP_SEND_ERROR = -12, /*!< */
224 | NET_TCP_READ_ERROR = -13, /*!< */
225 | NET_FUNC_NO_RDWR = -14, /*!< */
226 |
227 | }network_erro_codes_t;
228 |
229 |
230 |
231 |
232 |
233 | /******************************************************************************/
234 | /* */
235 | /* Ethernet Function Prototypes */
236 | /* */
237 | /******************************************************************************/
238 |
239 |
240 |
241 | /******************************************************
242 | * @brief Function to sum the data in network packet
243 | * @param *sum : Total 32 bit sum
244 | * @param *data : data to be summed
245 | * @param size_in_bytes : size of the data
246 | * @retval uint16_t : Error = -1, Success = 0
247 | ******************************************************/
248 | int8_t ether_sum_words(uint32_t *sum, void *data, uint16_t size_in_bytes);
249 |
250 |
251 |
252 | /******************************************************
253 | * @brief Function to get checksum of network packet
254 | * @param *sum : Total 32 bit sum
255 | * @retval uint16_t : checksum value
256 | ******************************************************/
257 | uint16_t ether_get_checksum(uint32_t sum);
258 |
259 |
260 |
261 |
262 | /******************************************************
263 | * @brief Function to get random number above a bound
264 | * @param *ethernet : reference to Ethernet handle
265 | * @param lower_bound : lower bound value
266 | * @retval uint16_t : Error = -1, Success = 0
267 | ******************************************************/
268 | int16_t get_random_port(ethernet_handle_t *ethernet, uint16_t lower_bound);
269 |
270 |
271 |
272 |
273 | /******************************************************
274 | * @brief Function to get random number above a bound
275 | * (32 bit)
276 | * @param *ethernet : reference to Ethernet handle
277 | * @param lower_bound : lower bound value
278 | * @retval uint32_t : Error = -1, Success = 0
279 | ******************************************************/
280 | int32_t get_random_port_l(ethernet_handle_t *ethernet, uint32_t lower_bound);
281 |
282 |
283 |
284 |
285 | /**************************************************************************
286 | * @brief constructor function to create Ethernet handle
287 | * (Multiple exit points)
288 | * @param *network_data : reference to the network data buffer
289 | * @param *mac_address : MAC address (string)
290 | * @param *ip_address : ip address (string)
291 | * @param *ether_ops : reference to the Ethernet operations structure
292 | * @retval int8_t : Error = NULL, Success = Ethernet object
293 | **************************************************************************/
294 | ethernet_handle_t* create_ethernet_handle(uint8_t *network_data, char *mac_address, char *ip_address, ether_operations_t *ether_ops);
295 |
296 |
297 |
298 |
299 |
300 | uint8_t ether_control(ethernet_handle_t *ethernet, ether_control_t ether_mode);
301 |
302 |
303 |
304 | /**********************************************************
305 | * @brief Function to get the Ethernet device status
306 | * @param *ethernet : reference to the Ethernet Handle
307 | * @retval uint8_t : Error = 0, Success = 1
308 | *********************************************************/
309 | uint8_t ether_module_status(ethernet_handle_t *ethernet);
310 |
311 |
312 |
313 | /***********************************************************
314 | * @brief Function get Ethernet network data
315 | * @param *ethernet : reference to the Ethernet handle
316 | * @param *data : network data
317 | * @param *data_length : source MAC address
318 | * @retval uint8_t : Error = 0, Success = 1
319 | ***********************************************************/
320 | uint8_t ether_get_data(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length);
321 |
322 |
323 |
324 | /***********************************************************
325 | * @brief Function send Ethernet network data
326 | * @param *ethernet : reference to the Ethernet handle
327 | * @param *data : network data
328 | * @param *data_length : source MAC address
329 | * @retval uint8_t : Error = 0, Success = 1
330 | ***********************************************************/
331 | uint8_t ether_send_data(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length);
332 |
333 |
334 |
335 | /**********************************************************************
336 | * @brief Function to fill the Ethernet frame
337 | * @param *ethernet : reference to the Ethernet handle
338 | * @param *destination_mac_address : destination MAC address
339 | * @param *source_mac_address : source MAC address
340 | * @param frame type : Ethernet frame type
341 | * @retval int8_t : Error = -1, Success = 0
342 | **********************************************************************/
343 | int8_t fill_ether_frame(ethernet_handle_t *ethernet, uint8_t *destination_mac_addr, uint8_t *source_mac_addr, ether_type_t frame_type);
344 |
345 |
346 |
347 | /***********************************************************
348 | * @brief Function get ethernet protocol type
349 | * @param *ethernet : reference to the Ethernet handle
350 | * @retval ether_type_t : Error = 0, Success = 1
351 | ***********************************************************/
352 | ether_type_t get_ether_protocol_type(ethernet_handle_t *ethernet);
353 |
354 |
355 |
356 | #endif /* ETHERNET_H_ */
357 |
--------------------------------------------------------------------------------
/NET_API/inc/icmp.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file icmp.h
4 | * @author Aditya Mall,
5 | * @brief ICMP (for IPV4) header file
6 | *
7 | * Info
8 | *
9 | ******************************************************************************
10 | * @attention
11 | *
12 | * © COPYRIGHT(c) 2019 Aditya Mall, MIT License
13 | *
14 | * MIT License
15 | *
16 | * Copyright (c) 2019 Aditya Mall
17 | *
18 | * Permission is hereby granted, free of charge, to any person obtaining a copy
19 | * of this software and associated documentation files (the "Software"), to deal
20 | * in the Software without restriction, including without limitation the rights
21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | * copies of the Software, and to permit persons to whom the Software is
23 | * furnished to do so, subject to the following conditions:
24 | *
25 | * The above copyright notice and this permission notice shall be included in all
26 | * copies or substantial portions of the Software.
27 | *
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | ******************************************************************************
40 | */
41 |
42 |
43 | #ifndef ICMP_H_
44 | #define ICMP_H_
45 |
46 |
47 |
48 |
49 | /*
50 | * Standard header and api header files
51 | */
52 | #include
53 |
54 | #include "ethernet.h"
55 |
56 |
57 | /******************************************************************************/
58 | /* */
59 | /* Data Structures and Defines */
60 | /* */
61 | /******************************************************************************/
62 |
63 |
64 | /* ICMP message types */
65 | typedef enum _icmp_type
66 | {
67 | ICMP_ECHOREPLY = 0, /*!< ICMP Echo reply code */
68 | ICMP_UNREACHABLE = 3, /*!< ICMP destination unreachable code */
69 | ICMP_ECHOREQUEST = 8, /*!< ICMP Echo request code */
70 | ICMP_TRACEROUTE = 30, /*!< ICMP Trace route code */
71 |
72 | }icmp_type_t;
73 |
74 |
75 |
76 |
77 | /******************************************************************************/
78 | /* */
79 | /* ICMP Function Prototypes */
80 | /* */
81 | /******************************************************************************/
82 |
83 |
84 |
85 |
86 | /******************************************************************
87 | * @brief Function to send ICMP reply packet
88 | * @param *ethernet : reference to the Ethernet handle
89 | * @retval int16_t : Error = -6, -7 = reply ignore, Success = 0
90 | ******************************************************************/
91 | int8_t ether_send_icmp_reply(ethernet_handle_t *ethernet);
92 |
93 |
94 |
95 | /*****************************************************************
96 | * @brief Function to send ICMP request
97 | * @param *ethernet : Reference to the Ethernet structure
98 | * @param icmp_type : ICMP request type
99 | * @param *destination_ip : Destination IP address
100 | * @param sequence_no : ICMP packet sequence Number
101 | * @param *destination_mac : Destination MAC address
102 | * @param *source_mac : Source MAC address
103 | * @retval int8_t : Error = -8, Success = 0.
104 | ****************************************************************/
105 | int8_t ether_send_icmp_req(ethernet_handle_t *ethernet, icmp_type_t icmp_type, uint8_t *destination_ip,
106 | uint8_t *sequence_no, uint8_t* destination_mac, uint8_t *source_mac);
107 |
108 |
109 | #endif /* ICMP_H_ */
110 |
--------------------------------------------------------------------------------
/NET_API/inc/ipv4.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file ipv4.h
4 | * @author Aditya Mall,
5 | * @brief IP version 4 protocol header file
6 | *
7 | * Info
8 | *
9 | ******************************************************************************
10 | * @attention
11 | *
12 | * © COPYRIGHT(c) 2019 Aditya Mall, MIT License
13 | *
14 | * MIT License
15 | *
16 | * Copyright (c) 2019 Aditya Mall
17 | *
18 | * Permission is hereby granted, free of charge, to any person obtaining a copy
19 | * of this software and associated documentation files (the "Software"), to deal
20 | * in the Software without restriction, including without limitation the rights
21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | * copies of the Software, and to permit persons to whom the Software is
23 | * furnished to do so, subject to the following conditions:
24 | *
25 | * The above copyright notice and this permission notice shall be included in all
26 | * copies or substantial portions of the Software.
27 | *
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | ******************************************************************************
40 | */
41 |
42 | #ifndef IPV4_H_
43 | #define IPV4_H_
44 |
45 |
46 | /*
47 | * Standard header and api header files
48 | */
49 | #include
50 |
51 | #include "ethernet.h"
52 |
53 |
54 |
55 |
56 | /******************************************************************************/
57 | /* */
58 | /* Data Structures and Defines */
59 | /* */
60 | /******************************************************************************/
61 |
62 |
63 | #define IP_VERSION 4 /*!< IP protocol version */
64 | #define IP_HEADER_LENGTH 5 /*!< IP header length value (not header size) */
65 | #define IP_DF_SET 0x4000 /*!< Don't Fragment set value */
66 | #define IP_TTL_VALUE 64 /*!< Time to Live value */
67 | #define IP_HEADER_SIZE 20 /*!< IP header size */
68 |
69 | /* IP version and header length fields */
70 | typedef struct _ip_ver_size
71 | {
72 | uint8_t header_length : 4; /*!< Header length value */
73 | uint8_t version : 4; /*!< IP version value */
74 |
75 | }ip_ver_size_t;
76 |
77 |
78 | /* IP Frame structure (20 Bytes in current implementation) */
79 | typedef struct _net_ip
80 | {
81 | ip_ver_size_t version_length; /*!< IP version and header length */
82 | uint8_t service_type; /*!< IP quality of service type */
83 | uint16_t total_length; /*!< IP packet total length */
84 | uint16_t id; /*!< IP packet ID */
85 | uint16_t flags_offset; /*!< IP fragmentation flags and offset */
86 | uint8_t ttl; /*!< Time to Live value */
87 | uint8_t protocol; /*!< IP protocol type */
88 | uint16_t header_checksum; /*!< IP header checksum */
89 | uint8_t source_ip[4]; /*!< Source IP address */
90 | uint8_t destination_ip[4]; /*!< Destination IP address */
91 |
92 | }net_ip_t;
93 |
94 |
95 | /* IP protocol type values */
96 | typedef enum _ip_protocol_type
97 | {
98 | IP_ICMP = 0x01,
99 | IP_TCP = 0x06,
100 | IP_UDP = 0x11,
101 |
102 | }ip_protocol_type_t;
103 |
104 |
105 |
106 |
107 | /******************************************************************************/
108 | /* */
109 | /* IPV4 Function Prototypes */
110 | /* */
111 | /******************************************************************************/
112 |
113 |
114 |
115 | /**************************************************************
116 | * @brief Function to get IP data for current host device
117 | * validates IP Checksum, (Only handles UNICAST)
118 | * @param *ethernet : reference to the Ethernet handle
119 | * @retval int16_t : Error = -4, -5,
120 | * Success = 1 (UNICAST),
121 | * = 2 (BROADCAST)
122 | **************************************************************/
123 | int16_t get_ip_communication_type(ethernet_handle_t *ethernet);
124 |
125 |
126 |
127 |
128 | /****************************************************************
129 | * @brief Function to get IP protocol type
130 | * @param *ethernet : reference to the Ethernet handle
131 | * @retval int16_t : Error = -4, -5, Success = protocol type
132 | ***************************************************************/
133 | ip_protocol_type_t get_ip_protocol_type(ethernet_handle_t *ethernet);
134 |
135 |
136 |
137 |
138 | /**********************************************************
139 | * @brief Function to fill the IP frame
140 | * @param *ip : reference to the IP structure
141 | * @param *id : reference to IP identifier
142 | * @param *destination_ip : destination IP address
143 | * @param *source_ip : source IP address
144 | * @param protocol : IP protocol type
145 | * @param data_size : size of payload
146 | * @retval int8_t : Error = NULL
147 | **********************************************************/
148 | int8_t fill_ip_frame(net_ip_t *ip, uint16_t *id, uint8_t *destination_ip, uint8_t *source_ip, ip_protocol_type_t protocol, uint16_t data_size);
149 |
150 |
151 |
152 |
153 | #endif /* IPV4_H_ */
154 |
--------------------------------------------------------------------------------
/NET_API/inc/network_utilities.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file network_utilities.h
4 | * @author Aditya Mall,
5 | * @brief Network utility header file
6 | *
7 | * Info
8 | *
9 | ******************************************************************************
10 | * @attention
11 | *
12 | * © COPYRIGHT(c) 2019 Aditya Mall, MIT License
13 | *
14 | * MIT License
15 | *
16 | * Copyright (c) 2019 Aditya Mall
17 | *
18 | * Permission is hereby granted, free of charge, to any person obtaining a copy
19 | * of this software and associated documentation files (the "Software"), to deal
20 | * in the Software without restriction, including without limitation the rights
21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | * copies of the Software, and to permit persons to whom the Software is
23 | * furnished to do so, subject to the following conditions:
24 | *
25 | * The above copyright notice and this permission notice shall be included in all
26 | * copies or substantial portions of the Software.
27 | *
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | ******************************************************************************
40 | */
41 |
42 | #ifndef NETWORK_UTILITIES_H_
43 | #define NETWORK_UTILITIES_H_
44 |
45 |
46 |
47 |
48 | /*
49 | * Standard header and api header files
50 | */
51 | #include
52 |
53 |
54 |
55 |
56 |
57 | /******************************************************************************/
58 | /* */
59 | /* Data Structures and Defines */
60 | /* */
61 | /******************************************************************************/
62 |
63 |
64 | /* defines network to host order function */
65 | #define ntohs htons
66 |
67 | #define ntohl htonl
68 |
69 |
70 | /******************************************************************************/
71 | /* */
72 | /* Network Utility Function Prototypes */
73 | /* */
74 | /******************************************************************************/
75 |
76 |
77 |
78 | /************************************************************************
79 | * @brief Function to convert from host to network order and vice versa
80 | * (For 16 bit data)
81 | * @retval uint16_t : host to network or network to host converted data
82 | ************************************************************************/
83 | uint16_t htons(uint16_t value);
84 |
85 |
86 |
87 | /************************************************************************
88 | * @brief Function to convert from host to network order and vice versa
89 | * (For 32 bit data)
90 | * Copyright (C) 1997-2019 Free Software Foundation, Inc.
91 | *
92 | * @retval uint32_t : host to network or network to host converted data
93 | ************************************************************************/
94 | uint32_t htonl(uint32_t x);
95 |
96 |
97 |
98 | /********************************************************
99 | * @brief Function to set mac address
100 | * @param *device_mac : device mac address (Hex)
101 | * @param *mac_address : mac address (string)
102 | * @retval int8_t : Error = -1, Success = 0
103 | ********************************************************/
104 | int8_t set_mac_address(uint8_t *device_mac, char *mac_address);
105 |
106 |
107 |
108 | /********************************************************
109 | * @brief function to set ip address
110 | * @param *host_ip : host ip address (integer)
111 | * @param *ip_address : ip address (string)
112 | * @retval int8_t : Error = -1, Success = 0
113 | ********************************************************/
114 | int8_t set_ip_address(uint8_t *host_ip, char *ip_address);
115 |
116 |
117 |
118 |
119 | /***********************************************
120 | * @brief Function to swap network address
121 | * (used in response messages)
122 | * @param *l_address : address value LHS
123 | * @param *r_address : address value RHS
124 | * @param size : size of address
125 | * @retval int8_t : Error = -1, Success = 0
126 | ***********************************************/
127 | int8_t net_swap_address(uint8_t* l_address, uint8_t *r_address, uint8_t size);
128 |
129 |
130 |
131 |
132 | /*********************************************************
133 | * @brief Function to set broadcast address
134 | * @param *destination_address : destination address
135 | * @param size : size of address
136 | * @retval int8_t : Error = -1, Success = 0
137 | *********************************************************/
138 | int8_t set_broadcast_address(uint8_t *destination_address, uint8_t size);
139 |
140 |
141 |
142 | #endif /* NETWORK_UTILITIES_H_ */
143 |
--------------------------------------------------------------------------------
/NET_API/inc/tcp.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file TCP.h
4 | * @author Aditya Mall,
5 | * @brief TCP protocol header file
6 | *
7 | * Info
8 | *
9 | ******************************************************************************
10 | * @attention
11 | *
12 | * © COPYRIGHT(c) 2019 Aditya Mall, MIT License
13 | *
14 | * MIT License
15 | *
16 | * Copyright (c) 2019 Aditya Mall
17 | *
18 | * Permission is hereby granted, free of charge, to any person obtaining a copy
19 | * of this software and associated documentation files (the "Software"), to deal
20 | * in the Software without restriction, including without limitation the rights
21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | * copies of the Software, and to permit persons to whom the Software is
23 | * furnished to do so, subject to the following conditions:
24 | *
25 | * The above copyright notice and this permission notice shall be included in all
26 | * copies or substantial portions of the Software.
27 | *
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | ******************************************************************************
40 | */
41 |
42 |
43 | #ifndef TCP_H_
44 | #define TCP_H_
45 |
46 |
47 | /*
48 | * Standard header and API header files
49 | */
50 | #include
51 | #include "ethernet.h"
52 |
53 |
54 | /******************************************************************************/
55 | /* */
56 | /* Data Structures and Defines */
57 | /* */
58 | /******************************************************************************/
59 |
60 | /* TCP ACK flags */
61 | typedef enum _tcp_control_flags
62 | {
63 |
64 | TCP_FIN = 0x01,
65 | TCP_SYN = 0x02,
66 | TCP_RST = 0x04,
67 | TCP_PSH = 0x08,
68 | TCP_ACK = 0x10,
69 | TCP_FIN_ACK = 0x11,
70 | TCP_SYN_ACK = 0x12,
71 | TCP_RST_ACK = 0x14,
72 | TCP_PSH_ACK = 0x18,
73 | TCP_FIN_PSH_ACK = 0x19,
74 |
75 | }tcp_ctl_flags_t;
76 |
77 |
78 | typedef enum _tcp_read_state
79 | {
80 | TCP_READ_BLOCKING = 1,
81 | TCP_READ_NONBLOCK = 2,
82 |
83 | }tcp_read_state_t;
84 |
85 |
86 | /* TCP client handle flags */
87 | typedef struct _tcp_client_flags
88 | {
89 | uint8_t connect_request : 1;
90 | uint8_t connect_established : 1;
91 | uint8_t server_tcp_reset : 1;
92 | uint8_t server_close : 1;
93 | uint8_t client_close : 1;
94 | uint8_t client_blocking : 1;
95 | uint8_t reserved : 2;
96 |
97 | }tcp_client_flags_t;
98 |
99 |
100 | /* TCP client handle */
101 | typedef struct _tcp_handle
102 | {
103 | uint16_t source_port;
104 | uint16_t destination_port;
105 | uint32_t sequence_number;
106 | uint32_t acknowledgement_number;
107 | uint8_t server_ip[4];
108 |
109 | tcp_client_flags_t client_flags;
110 |
111 |
112 | }tcp_handle_t;
113 |
114 |
115 |
116 | /******************************************************************************/
117 | /* */
118 | /* TCP Functions Prototypes */
119 | /* */
120 | /******************************************************************************/
121 |
122 |
123 |
124 | /********************************************************************
125 | * @brief Function to create TCP client object (STATIC)
126 | * @param source_port : TCP source port
127 | * @param destination_port : TCP destination port
128 | * @param *server_ip : Server IP
129 | * @retval int8_t : Error = 0, Success = TCP client object
130 | ********************************************************************/
131 | tcp_handle_t* ether_tcp_create_client(ethernet_handle_t *ethernet,
132 | uint8_t *network_data,
133 | uint16_t source_port,
134 | uint16_t destination_port,
135 | uint8_t *server_ip);
136 |
137 |
138 |
139 |
140 | /*****************************************************************
141 | * @brief Function to initialize TCP values to TCP client object
142 | * @param *client : Reference to TCP client handle
143 | * @param source_port : TCP source port
144 | * @param destination_port : TCP destination port
145 | * @param *server_ip : Server IP
146 | * @retval int8_t : Error = 0, Success = 1
147 | *****************************************************************/
148 | uint8_t tcp_init_client(tcp_handle_t *client,
149 | uint16_t source_port,
150 | uint16_t destination_port,
151 | uint8_t *server_ip);
152 |
153 |
154 |
155 |
156 | /**********************************************************
157 | * @brief Function to establish connection to TCP server
158 | * @param *ethernet : Reference to Ethernet handle
159 | * @param *network_data : Network data
160 | * @param *client : reference to TCP client handle
161 | * @retval int8_t : Error = -11, Success = 1
162 | **********************************************************/
163 | int8_t ether_tcp_connect(ethernet_handle_t *ethernet, uint8_t *network_data ,tcp_handle_t *client);
164 |
165 |
166 |
167 |
168 | /*****************************************************************
169 | * @brief Function to control TCP read behavior
170 | * @param *client : Reference to TCP handle
171 | * @param app_state : TCP read type (blocking or non blocking)
172 | * @retval int8_t : Error = 0, Success = 1
173 | ****************************************************************/
174 | int8_t tcp_control(tcp_handle_t *client, tcp_read_state_t app_state);
175 |
176 |
177 |
178 |
179 |
180 | /***************************************************************
181 | * @brief Function for sending TCP data
182 | * @param *ethernet : Reference to the Ethernet Handle
183 | * @param *network_data : Network data
184 | * @param *client : Reference to TCP client handle
185 | * @param *application_data : application_data
186 | * @param data_length : application data length
187 | * @retval int8_t : Error = -12,
188 | * Success = 1
189 | * -14(Connection closed)
190 | ***************************************************************/
191 | int32_t ether_tcp_send_data(ethernet_handle_t *ethernet,
192 | uint8_t *network_data,
193 | tcp_handle_t *client,
194 | char *application_data,
195 | uint16_t data_length);
196 |
197 |
198 |
199 |
200 |
201 | /************************************************************************
202 | * @brief helper function for reading TCP data
203 | * @param *ethernet : Reference to the Ethernet Handle
204 | * @param *network_data : Network data
205 | * @param *client : Reference to TCP client handle
206 | * @param *application_data : application_data
207 | * @param data_length : application data length
208 | * @retval uint16_t : Error = 0, Success = number of bytes read
209 | * 1 = ACK received
210 | ************************************************************************/
211 | int32_t ether_tcp_read_data(ethernet_handle_t *ethernet,
212 | uint8_t *network_data,
213 | tcp_handle_t *client,
214 | char *tcp_data,
215 | uint16_t data_length);
216 |
217 |
218 |
219 |
220 | /***************************************************************
221 | * @brief Function for close socket
222 | * @param *ethernet : Reference to the Ethernet Handle
223 | * @param *network_data : Network data
224 | * @param *client : Reference to TCP handle
225 | * @retval uint16_t : Error = 0, Success = 1;
226 | ***************************************************************/
227 | uint8_t ether_tcp_close(ethernet_handle_t *ethernet, uint8_t *network_data, tcp_handle_t *client);
228 |
229 |
230 |
231 |
232 | #endif /* TCP_H_ */
233 |
--------------------------------------------------------------------------------
/NET_API/inc/udp.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file udp.h
4 | * @author Aditya Mall,
5 | * @brief UDP protocol header file
6 | *
7 | * Info
8 | *
9 | ******************************************************************************
10 | * @attention
11 | *
12 | * © COPYRIGHT(c) 2019 Aditya Mall, MIT License
13 | *
14 | * MIT License
15 | *
16 | * Copyright (c) 2019 Aditya Mall
17 | *
18 | * Permission is hereby granted, free of charge, to any person obtaining a copy
19 | * of this software and associated documentation files (the "Software"), to deal
20 | * in the Software without restriction, including without limitation the rights
21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | * copies of the Software, and to permit persons to whom the Software is
23 | * furnished to do so, subject to the following conditions:
24 | *
25 | * The above copyright notice and this permission notice shall be included in all
26 | * copies or substantial portions of the Software.
27 | *
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | ******************************************************************************
40 | */
41 |
42 |
43 | #ifndef _UDP_H
44 | #define _UDP_H
45 |
46 |
47 |
48 | /*
49 | * Standard header and api header files
50 | */
51 | #include
52 |
53 | #include "ethernet.h"
54 |
55 |
56 |
57 |
58 | /******************************************************************************/
59 | /* */
60 | /* UDP Functions Prototypes */
61 | /* */
62 | /******************************************************************************/
63 |
64 |
65 |
66 | /**************************************************************
67 | * @brief Function get calculate UDP checksum
68 | * (UDP Headers + UDP data)
69 | * @param *ip : Reference to IP frame structure
70 | * @param *udp : Reference to UDP frame structure
71 | * @param data_length : Length of UDP data
72 | * @retval uint8_t : Error = 0, Success = checksum value
73 | **************************************************************/
74 | uint8_t ether_get_udp_data(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length);
75 |
76 |
77 |
78 |
79 | /*******************************************************************
80 | * @brief Raw Function to send UPD packets
81 | * UDP data dependent upon total data allocated to
82 | * ethernet object
83 | * @param *ethernet : Reference to the Ethernet handle
84 | * @param *source_addr : Reference to source address structure
85 | * @param *destination_ip : Destination IP address
86 | * @param *destination_mac : Destination MAC address
87 | * @param destination_port : UDP destination port
88 | * @param *data : UDP data
89 | * @param data_length : Length of UDP data
90 | * @retval int8_t : Error = -9, Success = 0
91 | *******************************************************************/
92 | int8_t ether_send_udp_raw(ethernet_handle_t *ethernet, ether_source_t *source_addr, uint8_t *destination_ip,
93 | uint8_t *destination_mac, uint16_t destination_port, uint8_t *data, uint16_t data_length);
94 |
95 |
96 |
97 |
98 | /****************************************************************
99 | * @brief Function detect UDP packet, state machine independent
100 | * @param *ethernet : Reference to the Ethernet handle
101 | * @param *network_data : network data from PHY
102 | * @param network_data_length : network data length to be read
103 | * @retval uint8_t : Error = 0,
104 | * Success = 1 (UNICAST)
105 | * = 2 (BROADCAST)
106 | ****************************************************************/
107 | uint8_t ether_is_udp(ethernet_handle_t *ethernet, uint8_t *network_data, uint16_t network_data_length);
108 |
109 |
110 |
111 |
112 |
113 | /*****************************************************************
114 | * @brief Function to read UPD packets
115 | * @param *ethernet : Reference to the Ethernet handle
116 | * @param *network_data : network data from PHY
117 | * @param *application_data : UDP data
118 | * @param app_data_length : Length of UDP data
119 | * @retval int8_t : Error = 0, Success = 1
120 | *****************************************************************/
121 | uint8_t ether_read_udp(ethernet_handle_t *ethernet, uint8_t *network_data, char *application_data, uint16_t app_data_length);
122 |
123 |
124 |
125 | /**************************************************************
126 | * @brief Function to send UPD packets
127 | * UDP data dependent upon total data allocated to
128 | * ethernet object
129 | * @param *ethernet : Reference to the Ethernet handle
130 | * @param *destination_ip : Destination IP address
131 | * @param destination_port : UDP destination port
132 | * @param *application_data : UDP data
133 | * @param data_length : Length of UDP data
134 | * @retval int8_t : Error = -10, Success = 0
135 | **************************************************************/
136 | int8_t ether_send_udp(ethernet_handle_t *ethernet, uint8_t *destination_ip, uint16_t destination_port,
137 | char *application_data, uint16_t data_length);
138 |
139 |
140 |
141 |
142 |
143 | /**************************************************************
144 | * @brief Function to read UDP packet
145 | * @param *ethernet : reference to the Ethernet handle
146 | * @param *network_data : network data from the ether PHY
147 | * @param net_data_length : network data length
148 | * @param *source_port : UDP source port
149 | * @param *destination_port : UDP destination port
150 | * @param *application_data : UDP data
151 | * @param data_length : Length of UDP data
152 | * @param app_data_length :
153 | * @retval uint16_t : Error = 0, Success = bytes read
154 | **************************************************************/
155 | uint16_t ether_read_udp_raw(ethernet_handle_t *ethernet, uint8_t *network_data, uint16_t net_data_length,
156 | uint16_t *source_port, uint16_t *destination_port, char *application_data, uint16_t app_data_length);
157 |
158 |
159 |
160 |
161 | #endif /* UDP_H_ */
162 |
--------------------------------------------------------------------------------
/NET_API/src/arp.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file arp.c
4 | * @author Aditya Mall,
5 | * @brief ARP Protocol source file
6 | *
7 | * Info
8 | *
9 | ******************************************************************************
10 | * @attention
11 | *
12 | * © COPYRIGHT(c) 2019 Aditya Mall, MIT License
13 | *
14 | * MIT License
15 | *
16 | * Copyright (c) 2019 Aditya Mall
17 | *
18 | * Permission is hereby granted, free of charge, to any person obtaining a copy
19 | * of this software and associated documentation files (the "Software"), to deal
20 | * in the Software without restriction, including without limitation the rights
21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | * copies of the Software, and to permit persons to whom the Software is
23 | * furnished to do so, subject to the following conditions:
24 | *
25 | * The above copyright notice and this permission notice shall be included in all
26 | * copies or substantial portions of the Software.
27 | *
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | ******************************************************************************
40 | */
41 |
42 |
43 | /*
44 | * Standard header and api header files
45 | */
46 | #include
47 | #include
48 |
49 |
50 | #include "arp.h"
51 | #include "network_utilities.h"
52 |
53 |
54 |
55 | /******************************************************************************/
56 | /* */
57 | /* Data Structures and Defines */
58 | /* */
59 | /******************************************************************************/
60 |
61 |
62 |
63 | /* ARP protocol structure */
64 | typedef struct _net_arp
65 | {
66 | uint16_t hardware_type; /*!< Network hardware type */
67 | uint16_t protocol_type; /*!< Network protocol type */
68 | uint8_t hardware_size; /*!< Hardware address (MAC) length */
69 | uint8_t protocol_size; /*!< Protocol address (IP) length */
70 | uint16_t opcode; /*!< Opcode */
71 | uint8_t sender_hw_addr[6]; /*!< Source hardware address */
72 | uint8_t sender_ip[4]; /*!< Source IP address */
73 | uint8_t target_hw_addr[6]; /*!< Destination hardware address */
74 | uint8_t target_ip[4]; /*!< Source hardware address */
75 |
76 | }net_arp_t;
77 |
78 |
79 | /* ARP protocol constant values */
80 | typedef enum _arp_protocol_constants
81 | {
82 | ARP_HRD_ETHERNET = 1, /*!< Value for hardware type (Ethernet) */
83 | ARP_PRO_IPV4 = 0x0800, /*!< Value for IPV4 protocol type */
84 | ARP_HLN = 6, /*!< Length of hardware address */
85 | ARP_PLN = 4 /*!< Length of IP address */
86 |
87 | }arp_protocol_constants_t;
88 |
89 |
90 |
91 | /* ARP protocol opcode values */
92 | typedef enum _arp_opcodes
93 | {
94 | ARP_REQUEST = 1,
95 | ARP_REPLY = 2,
96 | RARP_REQUEST = 3,
97 | RARP_REPLY = 4,
98 |
99 | }arp_opcodes_t;
100 |
101 |
102 |
103 |
104 |
105 | /******************************************************************************/
106 | /* */
107 | /* Private Functions */
108 | /* */
109 | /******************************************************************************/
110 |
111 |
112 |
113 | /********************************************************
114 | * @brief Static function to set broadcast mac address
115 | * @param *mac address : mac address to be configured
116 | * @retval int16_t : Error = -1, Success = 0
117 | ********************************************************/
118 | static int8_t set_broadcast_mac_addr(uint8_t *mac_address)
119 | {
120 | int8_t func_retval = 0;
121 |
122 | int8_t index = 0;
123 |
124 | if(mac_address == NULL)
125 | {
126 | func_retval = -1;
127 | }
128 | else
129 | {
130 | for(index = 0; index < 6; index++ )
131 | {
132 | mac_address[index] = 0xFF;
133 | }
134 | }
135 |
136 | return func_retval;
137 | }
138 |
139 |
140 |
141 |
142 | /******************************************************************************
143 | * @brief Static Function to update ARP table
144 | * @param *ethernet : reference to the Ethernet handle
145 | * @param *ip_address : device ip address
146 | * @param *mac_address : device mac_address
147 | * @retval int8_t : Success = 0 (device added), 1(device already exists)
148 | ******************************************************************************/
149 | static uint8_t update_arp_table(ethernet_handle_t *ethernet, uint8_t *ip_address, uint8_t *mac_address)
150 | {
151 |
152 | uint8_t func_retval = 0;
153 |
154 | uint8_t index = 0;
155 | uint8_t copy_index = 0;
156 |
157 | uint8_t found = 0;
158 |
159 | if(ethernet->ether_obj == NULL)
160 | {
161 | func_retval = 0;
162 | }
163 | else
164 | {
165 |
166 | for(index = 0; index < ARP_TABLE_SIZE; index++)
167 | {
168 | if( (memcmp(ethernet->arp_table[index].ip_address, ip_address, ETHER_IPV4_SIZE) == 0) )
169 | {
170 | found = 1;
171 |
172 | break;
173 | }
174 | else if( (strncmp((char*)ethernet->arp_table[index].ip_address, 0, ETHER_IPV4_SIZE) == 0) )
175 | {
176 | found = 0;
177 |
178 | /* Copy IP address */
179 | for(copy_index = 0; copy_index < ETHER_IPV4_SIZE; copy_index++)
180 | {
181 | ethernet->arp_table[index].ip_address[copy_index] = ip_address[copy_index];
182 | }
183 |
184 | /* Copy MAC address */
185 | for(copy_index = 0; copy_index < ETHER_MAC_SIZE; copy_index++)
186 | {
187 | ethernet->arp_table[index].mac_address[copy_index] = mac_address[copy_index];
188 | }
189 |
190 | break;
191 | }
192 | }
193 |
194 | func_retval = found;
195 | }
196 |
197 | return func_retval;
198 | }
199 |
200 |
201 |
202 |
203 | /******************************************************************************
204 | * @brief Static Function to search ARP table
205 | * @param *ethernet : reference to the Ethernet handle
206 | * @param *mac_address : device mac_address
207 | * @param *ip_address : device ip address
208 | * @retval int8_t : Success = 1 (address found)
209 | * Error = 0 (address not found)
210 | ******************************************************************************/
211 | static int8_t search_arp_table(ethernet_handle_t *ethernet, uint8_t *mac_address, uint8_t *ip_address)
212 | {
213 |
214 | int8_t func_retval = 0;
215 |
216 | uint8_t index = 0;
217 | uint8_t found = 0;
218 |
219 |
220 | for(index=0; index < ARP_TABLE_SIZE; index++)
221 | {
222 |
223 | if(memcmp(ethernet->arp_table[index].ip_address, ip_address , ETHER_IPV4_SIZE) == 0)
224 | {
225 |
226 | memcpy(mac_address, ethernet->arp_table[index].mac_address, ETHER_MAC_SIZE);
227 |
228 | found = 1;
229 |
230 | func_retval = found;
231 |
232 | break;
233 | }
234 |
235 | }
236 |
237 | return func_retval;
238 | }
239 |
240 |
241 |
242 |
243 |
244 | /******************************************************************************/
245 | /* */
246 | /* ARP Functions */
247 | /* */
248 | /******************************************************************************/
249 |
250 |
251 |
252 | /********************************************************
253 | * @brief Function to send arp request
254 | * @param *ethernet : reference to the Ethernet handle
255 | * @param *sender_ip : sender ip address
256 | * @param *target_ip : target ip address
257 | * @retval int16_t : Error = -1, Success = 0
258 | ********************************************************/
259 | int16_t ether_send_arp_req(ethernet_handle_t *ethernet, uint8_t *sender_ip, uint8_t *target_ip)
260 | {
261 | int16_t func_retval = 0;
262 |
263 | net_arp_t *arp;
264 |
265 | uint8_t broadcast_mac_addr[6] = {0};
266 | uint8_t i = 0;
267 |
268 | if(ethernet->ether_obj == NULL)
269 | {
270 | func_retval = NET_ARP_REQ_ERROR;
271 | }
272 | else
273 | {
274 | /* Link network object data */
275 | arp = (void*)ðernet->ether_obj->data;
276 |
277 |
278 | /* Set Broadcast MAC */
279 | set_broadcast_mac_addr(broadcast_mac_addr);
280 |
281 |
282 | /* Fill Ethernet frame */
283 | fill_ether_frame(ethernet, broadcast_mac_addr, ethernet->host_mac, ETHER_ARP);
284 |
285 |
286 | /* Fill ARP frame */
287 | arp->hardware_type = htons(ARP_HRD_ETHERNET);
288 | arp->protocol_type = htons(ARP_PRO_IPV4);
289 | arp->hardware_size = ARP_HLN;
290 | arp->protocol_size = ARP_PLN;
291 | arp->opcode = htons(ARP_REQUEST);
292 |
293 | for (i = 0; i < 6; i++)
294 | {
295 | arp->sender_hw_addr[i] = ethernet->host_mac[i];
296 | arp->target_hw_addr[i] = broadcast_mac_addr[i];
297 | }
298 |
299 | for (i = 0; i < 4; i++)
300 | {
301 | arp->sender_ip[i] = sender_ip[i];
302 | arp->target_ip[i] = target_ip[i];
303 | }
304 |
305 | /* Send packet (uses callback) */
306 | ether_send_data(ethernet, (uint8_t*)ethernet->ether_obj, ETHER_FRAME_SIZE + ARP_FRAME_SIZE);
307 | }
308 |
309 | return func_retval;
310 | }
311 |
312 |
313 |
314 |
315 | /**********************************************************
316 | * @brief Function to independently read ARP data
317 | * (Blocking Call)
318 | * @param *ethernet : reference to the Ethernet handle
319 | * @param *data : network_data
320 | * @param *data_length : length of data to be read
321 | * @retval uint8_t : Error = 0, Success = 1
322 | **********************************************************/
323 | uint8_t ether_is_arp(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length)
324 | {
325 | uint8_t func_retval = 0;
326 | uint8_t block_loop = 0;
327 |
328 | net_arp_t *arp;
329 |
330 | if(ethernet->ether_obj == NULL || data == NULL || data_length == 0 || data_length > UINT16_MAX)
331 | {
332 | func_retval = 0;
333 | }
334 | else
335 | {
336 | /* Wait for data */
337 | block_loop = 1;
338 |
339 | do
340 | {
341 | if(ether_get_data(ethernet, data, data_length))
342 | {
343 | /* Check if protocol is ARP */
344 | if(ntohs(ethernet->ether_obj->type) == ETHER_ARP)
345 | {
346 | arp = (void*)ðernet->ether_obj->data;
347 |
348 | if(memcmp(arp->target_hw_addr, ethernet->host_mac, ETHER_MAC_SIZE) == 0)
349 | {
350 |
351 | func_retval = 1;
352 |
353 | break;
354 | }
355 | }
356 | }
357 |
358 | }while(block_loop);
359 |
360 | }
361 |
362 | return func_retval;
363 | }
364 |
365 |
366 |
367 |
368 | /******************************************************************
369 | * @brief Function to handle ARP request and reply
370 | * sends ARP reply if ARP request received
371 | * @param *ethernet : reference to the Ethernet handle
372 | * @retval int16_t : Error = -2, -3 = reply ignore, Success = 0
373 | ******************************************************************/
374 | int16_t ether_handle_arp_resp_req(ethernet_handle_t *ethernet)
375 | {
376 | int16_t func_retval = 0;
377 |
378 | net_arp_t *arp;
379 |
380 | uint8_t i = 0;
381 |
382 | if(ethernet->ether_obj == NULL || ethernet->ether_obj->type != ntohs(ETHER_ARP))
383 | {
384 | func_retval = NET_ARP_RESP_ERROR;
385 | }
386 | else
387 | {
388 |
389 | arp = (void*)ðernet->ether_obj->data;
390 |
391 | /* Check if ARP request is for host IP */
392 | if( (strncmp((char*)arp->target_ip, (char*)ethernet->host_ip, 4) == 0) )
393 | {
394 | /* Handle APR request */
395 | if(arp->opcode == ntohs(ARP_REQUEST))
396 | {
397 |
398 | /* Get data into ARP Table */
399 | update_arp_table(ethernet, arp->sender_ip, arp->sender_hw_addr);
400 |
401 | /* Swap Ethernet MAC Address */
402 | for (i = 0; i < 6; i++)
403 | {
404 | ethernet->ether_obj->destination_mac_addr[i] = ethernet->ether_obj->source_mac_addr[i];
405 | ethernet->ether_obj->source_mac_addr[i] = ethernet->host_mac[i];
406 | }
407 |
408 | /* Fill ARP frame */
409 | arp->hardware_type = htons(ARP_HRD_ETHERNET);
410 | arp->protocol_type = htons(ARP_PRO_IPV4);
411 | arp->hardware_size = ARP_HLN;
412 | arp->protocol_size = ARP_PLN;
413 |
414 | arp->opcode = htons(ARP_REPLY);
415 |
416 | /* Swap ARP hardware/MAC address */
417 | for (i = 0; i < 6; i++)
418 | {
419 | arp->target_hw_addr[i] = arp->sender_hw_addr[i];
420 | arp->sender_hw_addr[i] = ethernet->host_mac[i];
421 | }
422 |
423 | /* Swap ARP IP address */
424 | for (i = 0; i < 4; i++)
425 | {
426 | arp->target_ip[i] = arp->sender_ip[i];
427 | arp->sender_ip[i] = ethernet->host_ip[i];
428 | }
429 |
430 | /* Send packet (uses callback) */
431 | ether_send_data(ethernet, (uint8_t*)ethernet->ether_obj, ETHER_FRAME_SIZE + 28);
432 | }
433 |
434 | /* Handle APR reply */
435 | else if(arp->opcode == ntohs(ARP_REPLY))
436 | {
437 | update_arp_table(ethernet, arp->sender_ip, arp->sender_hw_addr);
438 | }
439 |
440 | }
441 | else
442 | {
443 | func_retval = NET_ARP_RESP_IGNORE;
444 | }
445 |
446 | }
447 |
448 | return func_retval;
449 | }
450 |
451 |
452 |
453 |
454 |
455 | /***********************************************************************
456 | * @brief Function to get MAC address from destination IP address
457 | * by searching local ARP table
458 | * @param *ethernet : reference to the Ethernet handle
459 | * @param *mac_address : device mac_address
460 | * @param *ip_address : device ip address
461 | * @retval int8_t : Success = 1 device found else 0 for not found
462 | ***********************************************************************/
463 | uint8_t ether_arp_resolve_address(ethernet_handle_t *ethernet, uint8_t *destination_mac, uint8_t *destination_ip)
464 | {
465 |
466 | uint8_t func_retval = 0;
467 |
468 | /* Search arp table to find MAC address of the associated IP */
469 | func_retval = search_arp_table(ethernet, destination_mac, destination_ip);
470 |
471 |
472 | return func_retval;
473 | }
474 |
475 |
476 |
477 |
478 |
479 |
--------------------------------------------------------------------------------
/NET_API/src/dhcp.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file dhcp.c
4 | * @author Aditya Mall,
5 | * @brief DHCP protocol source file
6 | *
7 | * Info
8 | *
9 | ******************************************************************************
10 | * @attention
11 | *
12 | * © COPYRIGHT(c) 2019 Aditya Mall, MIT License
13 | *
14 | * MIT License
15 | *
16 | * Copyright (c) 2019 Aditya Mall
17 | *
18 | * Permission is hereby granted, free of charge, to any person obtaining a copy
19 | * of this software and associated documentation files (the "Software"), to deal
20 | * in the Software without restriction, including without limitation the rights
21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | * copies of the Software, and to permit persons to whom the Software is
23 | * furnished to do so, subject to the following conditions:
24 | *
25 | * The above copyright notice and this permission notice shall be included in all
26 | * copies or substantial portions of the Software.
27 | *
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | ******************************************************************************
40 | */
41 |
42 |
43 |
44 |
45 | /*
46 | * Standard header and api header files
47 | */
48 |
49 | #include
50 | #include
51 |
52 | #include "udp.h"
53 | #include "network_utilities.h"
54 | #include "dhcp.h"
55 | #include "arp.h"
56 |
57 |
58 |
59 | /******************************************************************************/
60 | /* */
61 | /* Data Structures and Defines */
62 | /* */
63 | /******************************************************************************/
64 |
65 |
66 | #pragma pack(1)
67 |
68 | #define DHCP_FRAME_SIZE 240
69 | #define DHCP_DISCOVER_OPTS_SIZE 18
70 | #define DHCP_REQUEST_OPTS_SIZE 36
71 |
72 |
73 |
74 | /* DHCP UDP port */
75 | typedef enum _network_ports
76 | {
77 | DHCP_DESTINATION_PORT = 67,
78 | DHCP_SOURCE_PORT = 68,
79 |
80 | }network_ports_t;
81 |
82 |
83 |
84 | /* DHCP FRAME (240 bytes), options variable data */
85 | typedef struct _net_dhcp
86 | {
87 | uint8_t op_code; /*!< Operation code or message type */
88 | uint8_t hw_type; /*!< Hardware type */
89 | uint8_t hw_length; /*!< Hardware length */
90 | uint8_t hops; /*!< Number of Hops */
91 | uint32_t transaction_id; /*!< */
92 | uint16_t seconds; /*!< */
93 | uint16_t flags; /*!< */
94 | uint8_t client_ip[4]; /*!< */
95 | uint8_t your_ip[4]; /*!< */
96 | uint8_t server_ip[4]; /*!< */
97 | uint8_t gateway_ip[4]; /*!< */
98 | uint8_t client_hw_addr[6]; /*!< */
99 | uint8_t client_hw_addr_pad[10]; /*!< */
100 | uint8_t server_name[64]; /*!< */
101 | uint8_t boot_filename[128]; /*!< */
102 | uint8_t magic_cookie[4]; /*!< */
103 | uint8_t options;
104 |
105 | }net_dhcp_t ;
106 |
107 |
108 |
109 |
110 | /************* DHCP Discover options structures **************/
111 |
112 | /* DHCP Option message type */
113 | typedef struct _opts_53
114 | {
115 | uint8_t option_number;
116 | uint8_t length;
117 | uint8_t dhcp;
118 |
119 | }dhcp_option_53_t;
120 |
121 |
122 | /* DHCP Option parameter request list */
123 | typedef struct _opts_55
124 | {
125 | uint8_t option_number;
126 | uint8_t length;
127 | uint8_t req_item[3];
128 |
129 | }dhcp_option_55_t;
130 |
131 |
132 | /* DHCP Option client identifier */
133 | typedef struct _opts_61
134 | {
135 | uint8_t option_number;
136 | uint8_t length;
137 | uint8_t hw_type;
138 | uint8_t client_mac[ETHER_MAC_SIZE];
139 |
140 | }dhcp_option_61_t;
141 |
142 |
143 |
144 | /* DHCP Discover options (18 bytes) */
145 | typedef struct _dhcp_discover_options
146 | {
147 | dhcp_option_53_t message_type;
148 | dhcp_option_55_t param_request_list;
149 | dhcp_option_61_t client_identifier;
150 | uint8_t options_end;
151 |
152 | }dhcp_discover_opts_t;
153 |
154 |
155 |
156 | /************* DHCP Offer options structures **************/
157 |
158 | /* */
159 | typedef struct _opts_54
160 | {
161 | uint8_t option_number;
162 | uint8_t length;
163 | uint8_t server_ip[ETHER_IPV4_SIZE];
164 |
165 | }dhcp_option_54_t;
166 |
167 | /* */
168 | typedef struct _opts_51
169 | {
170 | uint8_t option_number;
171 | uint8_t length;
172 | uint32_t lease_time;
173 |
174 | }dhcp_option_51_t;
175 |
176 | /* */
177 | typedef struct _opts_1
178 | {
179 | uint8_t option_number;
180 | uint8_t length;
181 | uint8_t subnet_mask[ETHER_IPV4_SIZE];
182 |
183 | }dhcp_option_1_t;
184 |
185 | /* */
186 | typedef struct _opts_3
187 | {
188 | uint8_t option_number;
189 | uint8_t length;
190 | uint8_t router[ETHER_IPV4_SIZE];
191 |
192 | }dhcp_option_3_t;
193 |
194 |
195 |
196 | /* DHCP Offer options */
197 | typedef struct _dhcp_offer_options
198 | {
199 | dhcp_option_53_t message_type;
200 | dhcp_option_54_t server_identifier;
201 | dhcp_option_51_t lease_time;
202 | dhcp_option_1_t subnet_mask;
203 | dhcp_option_3_t router;
204 | uint8_t options_end;
205 |
206 | }dhcp_offer_opts_t;
207 |
208 |
209 | /************* DHCP Offer Request structures **************/
210 |
211 |
212 | /* */
213 | typedef struct _opts_50
214 | {
215 | uint8_t option_number;
216 | uint8_t length;
217 | uint8_t requested_ip[ETHER_IPV4_SIZE];
218 |
219 | }dhcp_option_50_t;
220 |
221 |
222 |
223 | /* DHCP Request options */
224 | typedef struct _dhcp_request_options
225 | {
226 | dhcp_option_51_t lease_time;
227 | dhcp_option_53_t message_type;
228 | dhcp_option_55_t param_request_list;
229 | dhcp_option_61_t client_identifier;
230 | dhcp_option_50_t requested_ip;
231 | dhcp_option_54_t server_identifier;
232 | uint8_t options_end;
233 |
234 | }dhcp_request_opts_t;
235 |
236 |
237 |
238 | /* */
239 | typedef enum _dhcp_boot_message
240 | {
241 | DHCP_BOOT_REQ = 1,
242 | DHCP_BOOT_REPLY = 2,
243 | DHCP_DISCOVER = 1,
244 | DHCP_OFFER = 2,
245 | DHCP_REQUEST = 3,
246 | DHCP_ACK = 5,
247 |
248 | }dhcp_boot_msg_t;
249 |
250 |
251 |
252 | /* */
253 | typedef enum _dhcp_option_types
254 | {
255 | DHCP_SUBNET_MASK = 1,
256 | DHCP_ROUTER = 3,
257 | DHCP_REQUESTED_IP = 50,
258 | DHCP_ADDR_LEASE_TIME = 51,
259 | DHCP_MESSAGE_TYPE = 53,
260 | DHCP_SERVER_IDENTIFIER = 54,
261 | DHCP_PARAM_REQ_LIST = 55,
262 | DHCP_CLIENT_IDENTIFIER = 61,
263 | DHCP_OPTION_END = 255,
264 |
265 | }dhcp_options_types_t;
266 |
267 |
268 |
269 | /******************************************************************************/
270 | /* */
271 | /* DHCP Functions */
272 | /* */
273 | /******************************************************************************/
274 |
275 |
276 |
277 |
278 | /***************************************************************
279 | * @brief Function Send DHCP Discover
280 | * @param *ethernet : reference to the Ethernet handle
281 | * @param transaction_id : random transaction ID
282 | *
283 | * @param seconds_elapsed : number of seconds elapsed
284 | * @retval uint8_t : Error = -1, Success = 0
285 | ***************************************************************/
286 | int8_t ether_dhcp_send_discover(ethernet_handle_t *ethernet, uint32_t transaction_id, uint8_t *mac_address,
287 | uint16_t seconds_elapsed)
288 | {
289 |
290 | int8_t func_retval = 0;
291 |
292 | net_dhcp_t *dhcp_discover;
293 | dhcp_discover_opts_t *discover_opts;
294 | ether_source_t dhcp_client;
295 |
296 | uint8_t destination_ip[4] = {0};
297 | uint8_t destination_mac[6] = {0};
298 |
299 | char data[258] = {0};
300 |
301 | if(ethernet == NULL)
302 | {
303 | func_retval = -1;
304 | }
305 | else
306 | {
307 | /* Configure DHCP fields */
308 | dhcp_discover = (net_dhcp_t*)data;
309 |
310 | dhcp_discover->op_code = DHCP_BOOT_REQ;
311 | dhcp_discover->hw_type = 1;
312 | dhcp_discover->hw_length = ETHER_MAC_SIZE;
313 | dhcp_discover->hops = 0;
314 | dhcp_discover->transaction_id = htonl(transaction_id);
315 | dhcp_discover->seconds = htons(seconds_elapsed);
316 | dhcp_discover->flags = htons(0x8000);
317 |
318 | /* client IP address = 0 */
319 | /* your IP address = 0 */
320 | /* server IP address = 0 */
321 | /* gateway IP address = 0 */
322 |
323 | /* client hardware address */
324 | memcpy((char*)dhcp_discover->client_hw_addr, (char*)ethernet->host_mac, ETHER_MAC_SIZE);
325 |
326 | /* Client hardware address padding = 0 */
327 | /* Client Server host name = 0 */
328 | /* Client file name = 0 */
329 |
330 | /* Configure magic cookie value */
331 | dhcp_discover->magic_cookie[0] = 0x63;
332 | dhcp_discover->magic_cookie[1] = 0x82;
333 | dhcp_discover->magic_cookie[2] = 0x53;
334 | dhcp_discover->magic_cookie[3] = 0x63;
335 |
336 |
337 | /* Configure DHCP options */
338 | discover_opts = (void*)&dhcp_discover->options;
339 |
340 | /* option (53) */
341 | discover_opts->message_type.option_number = DHCP_MESSAGE_TYPE;
342 | discover_opts->message_type.length = 1;
343 | discover_opts->message_type.dhcp = DHCP_DISCOVER;
344 |
345 | /* option (55) */
346 | discover_opts->param_request_list.option_number = DHCP_PARAM_REQ_LIST;
347 | discover_opts->param_request_list.length = 3;
348 | discover_opts->param_request_list.req_item[0] = DHCP_SUBNET_MASK;
349 | discover_opts->param_request_list.req_item[1] = DHCP_ROUTER;
350 | discover_opts->param_request_list.req_item[2] = DHCP_ADDR_LEASE_TIME;
351 |
352 | /* option (61) */
353 | discover_opts->client_identifier.option_number = DHCP_CLIENT_IDENTIFIER;
354 | discover_opts->client_identifier.length = 7;
355 | discover_opts->client_identifier.hw_type = 1;
356 |
357 | memcpy((char*)discover_opts->client_identifier.client_mac, (char*)ethernet->host_mac, ETHER_MAC_SIZE);
358 |
359 | /* option end */
360 | discover_opts->options_end = DHCP_OPTION_END;
361 |
362 | /* Configure sources */
363 | memset(&dhcp_client, 0, sizeof(ether_source_t));
364 |
365 | dhcp_client.identifier = 1;
366 | dhcp_client.source_port = DHCP_SOURCE_PORT;
367 |
368 | memcpy((char*)dhcp_client.source_mac, (char*)mac_address, ETHER_MAC_SIZE);
369 |
370 | /* Configure destination address */
371 | memcpy((char*)destination_ip, (char*)ethernet->broadcast_ip, ETHER_IPV4_SIZE);
372 | memcpy((char*)destination_mac, (char*)ethernet->broadcast_mac, ETHER_MAC_SIZE);
373 |
374 |
375 | /* Send DHCP packet as UPD message */
376 | ether_send_udp_raw(ethernet, &dhcp_client, destination_ip, destination_mac, DHCP_DESTINATION_PORT,
377 | (uint8_t*)dhcp_discover, (DHCP_FRAME_SIZE + DHCP_DISCOVER_OPTS_SIZE));
378 | }
379 |
380 | return func_retval;
381 | }
382 |
383 |
384 |
385 |
386 | /************************************************************
387 | * @brief Function read DHCP offer
388 | * @param *ethernet : reference to the Ethernet handle
389 | * @param *network_data : network_data from PHY
390 | * @param *your_ip : 'your IP' address
391 | *
392 | * @param *dhcp_options : DHCP options data
393 | * @retval uint8_t : Error = 0, Success = DHCP type
394 | ************************************************************/
395 | int8_t ether_dhcp_read(ethernet_handle_t *ethernet, uint8_t *network_data, uint8_t *your_ip, uint32_t client_transac_id, uint8_t *dhcp_options)
396 | {
397 | int8_t func_retval = 0;
398 | uint16_t udp_message_length = 0;
399 |
400 | net_dhcp_t *dhcp_reply;
401 | dhcp_offer_opts_t *dhcp_opts;
402 |
403 | uint16_t udp_src_port = 0;
404 | uint16_t udp_dest_port = 0;
405 |
406 | char dhcp_data[APP_BUFF_SIZE] = {0};
407 |
408 | if(ethernet == NULL || network_data == NULL)
409 | {
410 | func_retval = 0;
411 | }
412 | else
413 | {
414 | /* read UDP packet */
415 | udp_message_length = ether_read_udp_raw(ethernet, network_data, ETHER_MTU_SIZE, &udp_src_port, &udp_dest_port, dhcp_data, APP_BUFF_SIZE);
416 |
417 |
418 | /* Check if UDP source ports = DHCP destination port */
419 | if(udp_src_port == DHCP_DESTINATION_PORT && udp_dest_port == DHCP_SOURCE_PORT && udp_message_length)
420 | {
421 | dhcp_reply = (void*)dhcp_data;
422 |
423 | if(client_transac_id == ntohl(dhcp_reply->transaction_id))
424 | {
425 |
426 | /* Get your_ip from DHCP standard header*/
427 | strncpy((char*)your_ip, (char*)dhcp_reply->your_ip, ETHER_IPV4_SIZE);
428 |
429 | /* Get server_ip, SUBNET mask, lease time from DHCP offer options */
430 | dhcp_opts = (void*)&dhcp_reply->options;
431 |
432 | func_retval = dhcp_opts->message_type.dhcp;
433 |
434 | memcpy(dhcp_options, (uint8_t*)dhcp_opts, (udp_message_length - DHCP_FRAME_SIZE));
435 | }
436 |
437 | }
438 |
439 | }
440 |
441 | return func_retval;
442 | }
443 |
444 |
445 |
446 |
447 |
448 |
449 | /************************************************************
450 | * @brief Function read DHCP offer (Depreciated)
451 | * @param *ethernet : reference to the Ethernet handle
452 | * @param *network_data : network_data from PHY
453 | * @param *your_ip : 'your IP' address
454 | * @param *server_ip : server IP address
455 | * @param *subnet_mask : SUBNET mask
456 | * @param *lease_time : IP address lease time
457 | * @retval uint8_t : Error = 0, Success = 1
458 | ************************************************************/
459 | int8_t ether_dhcp_read_offer(ethernet_handle_t *ethernet, uint8_t *network_data, uint8_t *your_ip, uint8_t *server_ip,
460 | uint8_t *subnet_mask, uint8_t *lease_time)
461 | {
462 | int8_t func_retval = 0;
463 | uint8_t api_retval = 0;
464 |
465 | net_dhcp_t *dhcp_offer;
466 | dhcp_offer_opts_t *offer_opts;
467 |
468 | uint16_t udp_src_port = 0;
469 | uint16_t udp_dest_port = 0;
470 |
471 | char dhcp_data[300] = {0};
472 |
473 | if(ethernet == NULL || network_data == NULL)
474 | {
475 | func_retval = 0;
476 | }
477 | else
478 | {
479 | /* read UDP packet */
480 | api_retval = ether_read_udp_raw(ethernet, network_data, 350, &udp_src_port, &udp_dest_port, dhcp_data, 300);
481 |
482 |
483 | /* Check if UDP source ports = DHCP destination port */
484 | if(udp_src_port == DHCP_DESTINATION_PORT && udp_dest_port == DHCP_SOURCE_PORT && api_retval)
485 | {
486 | dhcp_offer = (void*)dhcp_data;
487 |
488 | /* Get your_ip from DHCP standard header*/
489 | memcpy((char*)your_ip, (char*)dhcp_offer->your_ip, ETHER_IPV4_SIZE);
490 |
491 |
492 | /* Get server_ip, SUBNET mask, lease time from DHCP offer options */
493 | offer_opts = (void*)&dhcp_offer->options;
494 |
495 | memcpy((char*)server_ip, (char*)offer_opts->server_identifier.server_ip, ETHER_IPV4_SIZE);
496 |
497 | memcpy((char*)lease_time, (char*)offer_opts->lease_time.lease_time, ETHER_IPV4_SIZE);
498 |
499 | memcpy((char*)subnet_mask, (char*)offer_opts->subnet_mask.subnet_mask, ETHER_IPV4_SIZE);
500 |
501 |
502 | func_retval = 1;
503 | }
504 |
505 | }
506 |
507 | return func_retval;
508 | }
509 |
510 |
511 |
512 |
513 |
514 | /*************************************************************
515 | * @brief Function Send DHCP Request
516 | * @param *ethernet : reference to the Ethernet handle
517 | * @param transaction_id : random transaction ID
518 | * @param seconds_elapsed : number of seconds elapsed
519 | * @param *server_ip : DHCP server IP
520 | * @param *requested_ip : IP request to the server
521 | * @param *lease_time : Lease time
522 | * @retval uint8_t : Error = -1, Success = 0
523 | *************************************************************/
524 | int8_t ether_dhcp_send_request(ethernet_handle_t *ethernet, uint32_t transaction_id, uint16_t seconds_elapsed,
525 | uint8_t *server_ip, uint8_t *requested_ip, uint32_t lease_time)
526 | {
527 |
528 | int8_t func_retval = 0;
529 |
530 | net_dhcp_t *dhcp_request;
531 | dhcp_request_opts_t *request_opts;
532 | ether_source_t dhcp_client;
533 |
534 | uint8_t destination_ip[4] = {0};
535 | uint8_t destination_mac[6] = {0};
536 |
537 | char data[280] = {0};
538 |
539 | if(ethernet == NULL)
540 | {
541 | func_retval = -1;
542 | }
543 | else
544 | {
545 | /* Configure DHCP fields */
546 | dhcp_request = (net_dhcp_t*)data;
547 |
548 | dhcp_request->op_code = DHCP_BOOT_REQ;
549 | dhcp_request->hw_type = 1;
550 | dhcp_request->hw_length = ETHER_MAC_SIZE;
551 | dhcp_request->hops = 0;
552 | dhcp_request->transaction_id = htonl(transaction_id);
553 | dhcp_request->seconds = htons(seconds_elapsed);
554 | dhcp_request->flags = htons(0x8000);
555 |
556 | /* client IP address = 0 */
557 | /* your IP address = 0 */
558 | /* server IP address = 0 */
559 | /* gateway IP address = 0 */
560 |
561 | /* client hardware address */
562 | strncpy((char*)dhcp_request->client_hw_addr, (char*)ethernet->host_mac, ETHER_MAC_SIZE);
563 |
564 | /* Client hardware address padding = 0 */
565 | /* Client Server host name = 0 */
566 | /* Client file name = 0 */
567 |
568 | /* Configure magic cookie value */
569 | dhcp_request->magic_cookie[0] = 0x63;
570 | dhcp_request->magic_cookie[1] = 0x82;
571 | dhcp_request->magic_cookie[2] = 0x53;
572 | dhcp_request->magic_cookie[3] = 0x63;
573 |
574 |
575 | /* Configure DHCP options */
576 | request_opts = (void*)&dhcp_request->options;
577 |
578 |
579 | /* options (51) */
580 | request_opts->lease_time.option_number = DHCP_ADDR_LEASE_TIME;
581 | request_opts->lease_time.length = 4;
582 | //memcpy((char*)request_opts->lease_time.lease_time, (char*)lease_time, 4);
583 | request_opts->lease_time.lease_time = htonl(lease_time);
584 |
585 |
586 | /* option (53) */
587 | request_opts->message_type.option_number = DHCP_MESSAGE_TYPE;
588 | request_opts->message_type.length = 1;
589 | request_opts->message_type.dhcp = DHCP_REQUEST;
590 |
591 | /* option (55) */
592 | request_opts->param_request_list.option_number = DHCP_PARAM_REQ_LIST;
593 | request_opts->param_request_list.length = 3;
594 | request_opts->param_request_list.req_item[0] = DHCP_SUBNET_MASK;
595 | request_opts->param_request_list.req_item[1] = DHCP_ROUTER;
596 | request_opts->param_request_list.req_item[2] = DHCP_ADDR_LEASE_TIME;
597 |
598 | /* option (61) */
599 | request_opts->client_identifier.option_number = DHCP_CLIENT_IDENTIFIER;
600 | request_opts->client_identifier.length = 7;
601 | request_opts->client_identifier.hw_type = 1;
602 | memcpy((char*)request_opts->client_identifier.client_mac, (char*)ethernet->host_mac, ETHER_MAC_SIZE);
603 |
604 |
605 | /* options (50) */
606 | request_opts->requested_ip.option_number = DHCP_REQUESTED_IP;
607 | request_opts->requested_ip.length = 4;
608 | memcpy((char*)request_opts->requested_ip.requested_ip, (char*)requested_ip, ETHER_IPV4_SIZE);
609 |
610 |
611 | /* options (54) */
612 | request_opts->server_identifier.option_number = DHCP_SERVER_IDENTIFIER;
613 | request_opts->server_identifier.length = 4;
614 | memcpy((char*)request_opts->server_identifier.server_ip, (char*)server_ip, ETHER_IPV4_SIZE);
615 |
616 |
617 | /* option end */
618 | request_opts->options_end = DHCP_OPTION_END;
619 |
620 |
621 | /* Configure sources */
622 | memset(&dhcp_client, 0, sizeof(ether_source_t));
623 |
624 | dhcp_client.identifier = 1;
625 | dhcp_client.source_port = DHCP_SOURCE_PORT;
626 |
627 | memcpy((char*)dhcp_client.source_mac, (char*)ethernet->host_mac, ETHER_MAC_SIZE);
628 |
629 | /* Configure destination address */
630 | memcpy((char*)destination_ip, (char*)ethernet->broadcast_ip, ETHER_IPV4_SIZE);
631 | memcpy((char*)destination_mac, (char*)ethernet->broadcast_mac, ETHER_MAC_SIZE);
632 |
633 |
634 | /* Send DHCP packet as UPD message */
635 | ether_send_udp_raw(ethernet, &dhcp_client, destination_ip, destination_mac, DHCP_DESTINATION_PORT,
636 | (uint8_t*)dhcp_request, (DHCP_FRAME_SIZE + DHCP_REQUEST_OPTS_SIZE));
637 | }
638 |
639 | return func_retval;
640 | }
641 |
642 |
643 |
644 |
645 |
646 | /*************************************************************
647 | * @brief Function to get IP though DHCP state machine
648 | * @param *ethernet : reference to the Ethernet handle
649 | * @param *network_data : network data from PHY
650 | *
651 | * @param dhcp_state : DHCP state machine states
652 | * @retval uint8_t : Error = NA, Success = NA
653 | *************************************************************/
654 | int8_t ether_get_dhcp_ip(ethernet_handle_t *ethernet, uint8_t *network_data, uint8_t *mac_address,
655 | dhcp_states dhcp_state)
656 | {
657 |
658 | dhcp_offer_opts_t *offer_options;
659 |
660 | uint8_t your_ip[4] = {0};
661 | uint8_t server_ip[4] = {0};
662 | uint8_t subnet_mask[4] = {0};
663 | uint8_t dhcp_options[60] = {0};
664 |
665 | int8_t dhcp_type = 0;
666 | uint8_t dhcp_request_flag = 0;
667 | uint8_t dhcp_loop = 1;
668 |
669 | uint32_t dhcp_transac_id = get_random_port_l(ethernet, 65535);
670 |
671 | dhcp_state = DHCP_INIT_STATE;
672 |
673 | uint32_t lease_time = 0;
674 |
675 | while(dhcp_loop)
676 | {
677 | switch(dhcp_state)
678 | {
679 |
680 | case DHCP_INIT_STATE:
681 |
682 | ethernet->status.mode_dhcp_init = 1;
683 |
684 | dhcp_state = DHCP_SELECTING_STATE;
685 |
686 | break;
687 |
688 |
689 | case DHCP_SELECTING_STATE:
690 |
691 | ether_dhcp_send_discover(ethernet, dhcp_transac_id, mac_address, 0);
692 |
693 | dhcp_state = DHCP_READ_STATE;
694 |
695 | break;
696 |
697 |
698 | case DHCP_READ_STATE:
699 |
700 | dhcp_type = ether_dhcp_read(ethernet, (uint8_t*)network_data, your_ip, dhcp_transac_id, dhcp_options);
701 |
702 | /* Handle DHCP offer */
703 | if(dhcp_type == DHCP_OFFER && ethernet->status.mode_dhcp_init == 1 && dhcp_request_flag == 0)
704 | {
705 | /* Get server_ip, SUBNET mask, lease time from DHCP offer options */
706 | offer_options = (void*)dhcp_options;
707 |
708 | memcpy(server_ip, offer_options->server_identifier.server_ip, ETHER_IPV4_SIZE);
709 | memcpy(subnet_mask, offer_options->subnet_mask.subnet_mask, ETHER_IPV4_SIZE);
710 |
711 | lease_time = ntohl(offer_options->lease_time.lease_time);
712 |
713 | dhcp_state = DHCP_REQUESTING_STATE;
714 | break;
715 |
716 | }
717 | /* Handle DHCP ACK */
718 | else if(dhcp_type == DHCP_ACK && dhcp_request_flag == 1)
719 | {
720 | dhcp_state = DHCP_ACK_STATE;
721 | break;
722 | }
723 | /* Handle DHCP offer or request not received conditions */
724 | else if(dhcp_request_flag == 1)
725 | {
726 | dhcp_state = DHCP_REQUESTING_STATE;
727 | break;
728 | }
729 | else if(ethernet->status.mode_dhcp_init == 1)
730 | {
731 | dhcp_state = DHCP_SELECTING_STATE;
732 | }
733 |
734 |
735 | break;
736 |
737 |
738 | case DHCP_REQUESTING_STATE:
739 |
740 | ether_dhcp_send_request(ethernet, dhcp_transac_id, 1, server_ip, your_ip, lease_time);
741 |
742 | dhcp_request_flag = 1;
743 |
744 | dhcp_state = DHCP_READ_STATE;
745 |
746 | break;
747 |
748 |
749 | case DHCP_ACK_STATE:
750 |
751 | dhcp_request_flag = 0;
752 |
753 | memcpy((char*)ethernet->host_ip, (char*)your_ip, 4);
754 |
755 | memcpy((char*)ethernet->gateway_ip, (char*)server_ip, 4);
756 |
757 | memcpy((char*)ethernet->subnet_mask, (char*)subnet_mask, 4);
758 |
759 | ethernet->lease_time = lease_time;
760 |
761 | dhcp_state = DHCP_BOUND_STATE;
762 |
763 | break;
764 |
765 |
766 | case DHCP_BOUND_STATE:
767 |
768 | ethernet->status.mode_dhcp_init = 0;
769 | ethernet->status.mode_dhcp_bound = 1;
770 | ethernet->status.mode_dynamic = 1;
771 |
772 | dhcp_loop = 0;
773 |
774 | ether_send_arp_req(ethernet, ethernet->host_ip, ethernet->gateway_ip);
775 |
776 | if(ether_is_arp(ethernet, (uint8_t*)network_data, 128))
777 | {
778 |
779 | ether_handle_arp_resp_req(ethernet);
780 |
781 | }
782 |
783 |
784 | break;
785 |
786 |
787 | default:
788 |
789 | dhcp_loop = 0;
790 |
791 | break;
792 |
793 | }
794 |
795 | }
796 |
797 |
798 | return 0;
799 | }
800 |
801 |
802 |
803 |
804 |
--------------------------------------------------------------------------------
/NET_API/src/ethernet.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file ethernet.c
4 | * @author Aditya Mall,
5 | * @brief ethernet layer source file
6 | *
7 | * Info
8 | *
9 | ******************************************************************************
10 | * @attention
11 | *
12 | * © COPYRIGHT(c) 2019 Aditya Mall, MIT License
13 | *
14 | * MIT License
15 | *
16 | * Copyright (c) 2019 Aditya Mall
17 | *
18 | * Permission is hereby granted, free of charge, to any person obtaining a copy
19 | * of this software and associated documentation files (the "Software"), to deal
20 | * in the Software without restriction, including without limitation the rights
21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | * copies of the Software, and to permit persons to whom the Software is
23 | * furnished to do so, subject to the following conditions:
24 | *
25 | * The above copyright notice and this permission notice shall be included in all
26 | * copies or substantial portions of the Software.
27 | *
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | ******************************************************************************
40 | */
41 |
42 |
43 |
44 | /*
45 | * Standard header and api header files
46 | */
47 |
48 | #include
49 | #include
50 | #include
51 |
52 | #include "ethernet.h"
53 | #include "network_utilities.h"
54 |
55 |
56 |
57 |
58 | /******************************************************************************/
59 | /* */
60 | /* Ethernet Functions */
61 | /* */
62 | /******************************************************************************/
63 |
64 |
65 |
66 | /* Weak implementations of Ethernet operation functions */
67 |
68 | __attribute__((weak))int16_t ethernet_send_packet(uint8_t *data, uint16_t length)
69 | {
70 |
71 | return 0;
72 | }
73 |
74 |
75 |
76 | __attribute__((weak))uint16_t ethernet_recv_packet(uint8_t *data, uint16_t length)
77 | {
78 |
79 | return 0;
80 | }
81 |
82 |
83 |
84 | __attribute__((weak))uint16_t random_seed(void)
85 | {
86 |
87 | return 0;
88 | }
89 |
90 |
91 |
92 |
93 | /******************************************************
94 | * @brief Function to sum the data in network packet
95 | * @param *sum : Total 32 bit sum
96 | * @param *data : data to be summed
97 | * @param size_in_bytes : size of the data
98 | * @retval uint16_t : Error = -1, Success = 0
99 | ******************************************************/
100 | int8_t ether_sum_words(uint32_t *sum, void *data, uint16_t size_in_bytes)
101 | {
102 |
103 | int8_t func_retval = 0;
104 |
105 | uint8_t *data_ptr = (uint8_t *)data;
106 |
107 | uint16_t data_temp;
108 | uint8_t phase = 0;
109 |
110 | uint16_t i = 0;
111 |
112 | if(data == NULL)
113 | {
114 | func_retval = -1;
115 | }
116 | else
117 | {
118 | for(i = 0; i < size_in_bytes; i++)
119 | {
120 | if(phase)
121 | {
122 | data_temp = *data_ptr;
123 |
124 | *sum += data_temp << 8;
125 | }
126 | else
127 | {
128 | *sum += *data_ptr;
129 | }
130 |
131 | phase = 1 - phase;
132 |
133 | data_ptr++;
134 | }
135 | }
136 |
137 | return func_retval;
138 | }
139 |
140 |
141 |
142 |
143 | /******************************************************
144 | * @brief Function to get checksum of network packet
145 | * @param *sum : Total 32 bit sum
146 | * @retval uint16_t : checksum value
147 | ******************************************************/
148 | uint16_t ether_get_checksum(uint32_t sum)
149 | {
150 | uint16_t checksum = 0;
151 |
152 | while ((sum >> 16) > 0)
153 | {
154 | /* this is based on rfc1071 */
155 | sum = (sum & 0xFFFF) + (sum >> 16);
156 | }
157 |
158 | checksum = sum & 0xFFFF;
159 |
160 | checksum = ~checksum;
161 |
162 | /* return 1s complement */
163 | return checksum;
164 | }
165 |
166 |
167 |
168 |
169 | /******************************************************
170 | * @brief Function to get random number above a bound
171 | * @param *ethernet : reference to Ethernet handle
172 | * @param lower_bound : lower bound value
173 | * @retval uint16_t : Error = -1, Success = 0
174 | ******************************************************/
175 | int16_t get_random_port(ethernet_handle_t *ethernet, uint16_t lower_bound)
176 | {
177 | int16_t func_retval = 0;
178 |
179 | uint16_t random_seed = 0;
180 | uint16_t random_number = 0;
181 |
182 | if(ethernet->ether_obj == NULL)
183 | {
184 | func_retval = -1;
185 | }
186 | else
187 | {
188 |
189 | random_seed = ethernet->ether_commands->random_gen_seed();
190 |
191 | srand(random_seed);
192 |
193 | lower_bound += random_seed;
194 |
195 | random_number = ( rand() % (UINT16_MAX - lower_bound) ) + lower_bound;
196 |
197 | random_number += ethernet->ether_commands->random_gen_seed();
198 |
199 | func_retval = random_number;
200 | }
201 |
202 | return func_retval;
203 | }
204 |
205 |
206 |
207 |
208 | /******************************************************
209 | * @brief Function to get random number above a bound
210 | * (32 bit)
211 | * @param *ethernet : reference to Ethernet handle
212 | * @param lower_bound : lower bound value
213 | * @retval uint32_t : Error = -1, Success = 0
214 | ******************************************************/
215 | int32_t get_random_port_l(ethernet_handle_t *ethernet, uint32_t lower_bound)
216 | {
217 | int32_t func_retval = 0;
218 |
219 | uint16_t random_seed = 0;
220 | uint32_t random_number = 0;
221 |
222 | if(ethernet->ether_obj == NULL)
223 | {
224 | func_retval = -1;
225 | }
226 | else
227 | {
228 | random_seed = ethernet->ether_commands->random_gen_seed();
229 |
230 | srand(ethernet->ether_commands->random_gen_seed());
231 |
232 | lower_bound += (uint32_t)random_seed;
233 |
234 | random_number = ( rand() % (UINT32_MAX - lower_bound) ) + lower_bound;
235 |
236 | func_retval = random_number;
237 | }
238 |
239 | return func_retval;
240 | }
241 |
242 |
243 |
244 |
245 | /**************************************************************************
246 | * @brief constructor function to create Ethernet handle
247 | * (Multiple exit points)
248 | * @param *network_data : reference to the network data buffer
249 | * @param *mac_address : MAC address (string)
250 | * @param *ip_address : ip address (string)
251 | * @param *ether_ops : reference to the Ethernet operations structure
252 | * @retval int8_t : Error = NULL, Success = Ethernet object
253 | **************************************************************************/
254 | ethernet_handle_t* create_ethernet_handle(uint8_t *network_data, char *mac_address, char *ip_address, ether_operations_t *ether_ops)
255 | {
256 |
257 | static ethernet_handle_t ethernet;
258 |
259 | static char application_buffer[APP_BUFF_SIZE] = {0};
260 |
261 | int8_t api_retval = 0;
262 |
263 | if(network_data == NULL)
264 | {
265 | return NULL;
266 | }
267 | else
268 | {
269 | /* Give starting address of network data to*/
270 | ethernet.ether_obj = (void*)network_data;
271 |
272 | /* Set source addresses */
273 | api_retval = set_mac_address(ethernet.host_mac, mac_address);
274 |
275 | api_retval = set_ip_address(ethernet.host_ip, ip_address);
276 |
277 | /* Set default modes */
278 | ethernet.status.mode_static = 1;
279 | ethernet.status.mode_dynamic = 0;
280 | ethernet.status.mode_dhcp_init = 0;
281 | ethernet.status.mode_read_blocking = ETHER_READ_BLOCK;
282 |
283 | /* Configure broadcast addresses */
284 | set_broadcast_address(ethernet.broadcast_mac, ETHER_MAC_SIZE);
285 |
286 | set_broadcast_address(ethernet.broadcast_ip, ETHER_IPV4_SIZE);
287 |
288 |
289 | if(api_retval < 0)
290 | return NULL;
291 |
292 |
293 | /* Configure application buffer */
294 | ethernet.net_application_data = application_buffer;
295 |
296 | /* Configure network operations and weak linking of default functions */
297 | ethernet.ether_commands = ether_ops;
298 |
299 | if(ethernet.ether_commands->open == NULL)
300 | return NULL;
301 |
302 | if(ethernet.ether_commands->network_interface_status == NULL)
303 | return NULL;
304 |
305 | if(ethernet.ether_commands->random_gen_seed == NULL)
306 | ethernet.ether_commands->random_gen_seed = random_seed;
307 |
308 | if(ethernet.ether_commands->ether_send_packet == NULL)
309 | ethernet.ether_commands->ether_send_packet = ethernet_send_packet;
310 |
311 | if(ethernet.ether_commands->ether_recv_packet == NULL)
312 | ethernet.ether_commands->ether_recv_packet = ethernet_recv_packet;
313 |
314 |
315 | /* Functions called after linking */
316 |
317 | /* configure sources */
318 | ethernet.ip_identifier = get_unique_id(ðernet, 2000);
319 | ethernet.source_port = get_random_port(ðernet, 2000);
320 |
321 |
322 | /* Initialize Ethernet */
323 | ethernet.ether_commands->open(ethernet.host_mac);
324 |
325 |
326 | }
327 |
328 | return ðernet;
329 | }
330 |
331 |
332 |
333 | uint8_t ether_control(ethernet_handle_t *ethernet, ether_control_t ether_mode)
334 | {
335 |
336 | if(ether_mode == ETHER_READ_NONBLOCK)
337 | {
338 | ethernet->status.mode_read_blocking = ETHER_READ_NONBLOCK;
339 | }
340 |
341 |
342 | return 0;
343 | }
344 |
345 |
346 |
347 |
348 |
349 | /**********************************************************
350 | * @brief Function to get the Ethernet device status
351 | * @param *ethernet : reference to the Ethernet Handle
352 | * @retval uint8_t : Error = 0, Success = 1
353 | *********************************************************/
354 | uint8_t ether_module_status(ethernet_handle_t *ethernet)
355 | {
356 | uint8_t func_retval = 0;
357 |
358 | if(ethernet->ether_obj == NULL)
359 | {
360 | func_retval = 0;
361 | }
362 | else
363 | {
364 | if(ethernet->ether_commands->function_lock == 0)
365 | {
366 | ethernet->ether_commands->function_lock = 1;
367 |
368 | func_retval = ethernet->ether_commands->network_interface_status();
369 |
370 | ethernet->ether_commands->function_lock = 0;
371 | }
372 | }
373 |
374 | return func_retval;
375 | }
376 |
377 |
378 |
379 | /***********************************************************
380 | * @brief Function Ethernet network data
381 | * @param *ethernet : reference to the Ethernet handle
382 | * @param *data : network data
383 | * @param *data_length : source MAC address
384 | * @retval uint8_t : Error = 0, Success = 1
385 | ***********************************************************/
386 | uint8_t ether_get_data(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length)
387 | {
388 |
389 | uint8_t func_retval = 0;
390 |
391 | if(ethernet->ether_obj == NULL || data == NULL || data_length == 0 || data_length > UINT16_MAX)
392 | {
393 | func_retval = 0;
394 | }
395 | else
396 | {
397 | if(ether_module_status(ethernet))
398 | {
399 | ethernet->ether_commands->function_lock = 1;
400 |
401 | /* get data from network including PHY module frame */
402 | ethernet->ether_commands->ether_recv_packet(data, data_length);
403 |
404 | func_retval = 1;
405 |
406 | ethernet->ether_commands->function_lock = 0;
407 | }
408 |
409 | }
410 |
411 | return func_retval;
412 | }
413 |
414 |
415 |
416 | /***********************************************************
417 | * @brief Function send Ethernet network data
418 | * @param *ethernet : reference to the Ethernet handle
419 | * @param *data : network data
420 | * @param *data_length : source MAC address
421 | * @retval uint8_t : Error = 0, Success = 1
422 | ***********************************************************/
423 | uint8_t ether_send_data(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length)
424 | {
425 |
426 | uint8_t func_retval = 0;
427 |
428 | if(ethernet->ether_obj == NULL || data == NULL || data_length == 0 || data_length > UINT16_MAX)
429 | {
430 | func_retval = 0;
431 | }
432 | else
433 | {
434 | ethernet->ether_commands->function_lock = 1;
435 |
436 | ethernet->ether_commands->ether_send_packet(data, data_length);
437 |
438 | func_retval = 1;
439 |
440 | ethernet->ether_commands->function_lock = 0;
441 |
442 | }
443 |
444 | return func_retval;
445 | }
446 |
447 |
448 |
449 | /**********************************************************************
450 | * @brief Function to fill the Ethernet frame
451 | * @param *ethernet : reference to the Ethernet handle
452 | * @param *destination_mac_address : destination MAC address
453 | * @param *source_mac_address : source MAC address
454 | * @param frame type : Ethernet frame type
455 | * @retval int8_t : Error = -1, Success = 0
456 | **********************************************************************/
457 | int8_t fill_ether_frame(ethernet_handle_t *ethernet, uint8_t *destination_mac_addr, uint8_t *source_mac_addr, ether_type_t frame_type)
458 | {
459 | int8_t func_retval = 0;
460 |
461 | uint8_t index = 0;
462 |
463 | if(ethernet->ether_obj == NULL || destination_mac_addr == NULL || source_mac_addr == NULL)
464 | {
465 | func_retval = -1;
466 | }
467 | else
468 | {
469 | /* Fill MAC address */
470 | for(index = 0; index < 6; index++)
471 | {
472 | ethernet->ether_obj->destination_mac_addr[index] = destination_mac_addr[index];
473 | ethernet->ether_obj->source_mac_addr[index] = source_mac_addr[index];
474 | }
475 |
476 | ethernet->ether_obj->type = htons(frame_type);
477 | }
478 |
479 | return func_retval;
480 | }
481 |
482 |
483 |
484 |
485 | /***********************************************************
486 | * @brief Function get ethernet protocol type
487 | * @param *ethernet : reference to the Ethernet handle
488 | * @retval ether_type_t : Error = 0, Success = 1
489 | ***********************************************************/
490 | ether_type_t get_ether_protocol_type(ethernet_handle_t *ethernet)
491 | {
492 |
493 | ether_type_t func_retval;
494 |
495 | if(ethernet == NULL || ethernet->ether_obj == NULL)
496 | {
497 | func_retval = (ether_type_t)0;
498 | }
499 | else
500 | {
501 | func_retval = (ether_type_t)(ntohs(ethernet->ether_obj->type));
502 | }
503 |
504 | return func_retval;
505 |
506 | }
507 |
508 |
509 |
510 |
511 |
512 |
--------------------------------------------------------------------------------
/NET_API/src/icmp.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file icmp.c
4 | * @author Aditya Mall,
5 | * @brief ICMP (for IPV4) source file
6 | *
7 | * Info
8 | *
9 | ******************************************************************************
10 | * @attention
11 | *
12 | * © COPYRIGHT(c) 2019 Aditya Mall, MIT License
13 | *
14 | * MIT License
15 | *
16 | * Copyright (c) 2019 Aditya Mall
17 | *
18 | * Permission is hereby granted, free of charge, to any person obtaining a copy
19 | * of this software and associated documentation files (the "Software"), to deal
20 | * in the Software without restriction, including without limitation the rights
21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | * copies of the Software, and to permit persons to whom the Software is
23 | * furnished to do so, subject to the following conditions:
24 | *
25 | * The above copyright notice and this permission notice shall be included in all
26 | * copies or substantial portions of the Software.
27 | *
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | ******************************************************************************
40 | */
41 |
42 |
43 |
44 |
45 | /*
46 | * Standard header and api header files
47 | */
48 | #include
49 | #include
50 |
51 | #include "icmp.h"
52 | #include "ipv4.h"
53 | #include "network_utilities.h"
54 |
55 | #include
56 |
57 | /******************************************************************************/
58 | /* */
59 | /* Data Structures and Defines */
60 | /* */
61 | /******************************************************************************/
62 |
63 |
64 | #define ICMP_FRAME_SIZE 8
65 |
66 |
67 |
68 | /* ICMP Frame (8 bytes) */
69 | typedef struct _net_icmp
70 | {
71 | uint8_t type; /*!< ICMP message type */
72 | uint8_t code; /*!< ICMP code for subtype messages */
73 | uint16_t checksum; /*!< ICMP message checksum */
74 | uint16_t id; /*!< ICMP message ID */
75 | uint16_t sequence_no; /*!< ICMP message sequence number */
76 | uint8_t data; /*!< ICMP message data */
77 |
78 | } net_icmp_t;
79 |
80 |
81 |
82 |
83 | /******************************************************************************/
84 | /* */
85 | /* ICMP Functions */
86 | /* */
87 | /******************************************************************************/
88 |
89 |
90 |
91 |
92 | /******************************************************************
93 | * @brief Function to send ICMP reply packet
94 | * @param *ethernet : reference to the Ethernet handle
95 | * @retval int16_t : Error = -6, -7 = reply ignore, Success = 0
96 | ******************************************************************/
97 | int8_t ether_send_icmp_reply(ethernet_handle_t *ethernet)
98 | {
99 | int8_t func_retval = 0;
100 |
101 | net_ip_t *ip;
102 | net_icmp_t *icmp;
103 |
104 | uint32_t sum = 0;
105 | uint16_t ip_header_size = 0;
106 | uint16_t ip_packet_length = 0;
107 | uint16_t icmp_remaining_size = 0;
108 |
109 | if(ethernet->ether_obj == NULL)
110 | {
111 | func_retval = NET_ICMP_RESP_ERROR;
112 | }
113 | else
114 | {
115 | ip = (void*)ðernet->ether_obj->data;
116 |
117 | ip_header_size = ip->version_length.header_length * 4;
118 |
119 | icmp = (void*)( (uint8_t*)ip + ip_header_size);
120 |
121 | /* Send ECHO reply */
122 | if(icmp->type == ICMP_ECHOREQUEST)
123 | {
124 | /* Swap MAC address in Ethernet Frame */
125 | net_swap_address(ethernet->ether_obj->destination_mac_addr, ethernet->ether_obj->source_mac_addr, 6);
126 |
127 | /* Swap IP address in IP Frame */
128 | net_swap_address(ip->destination_ip, ip->source_ip, 4);
129 |
130 | /* Fill ICMP frame */
131 | icmp->type = ICMP_ECHOREPLY;
132 |
133 | /*** Calculate ICMP Checksum ***/
134 |
135 | ether_sum_words(&sum, &icmp->type, 2);
136 |
137 | /* get total length of IP packet */
138 | ip_packet_length = ntohs(ip->total_length);
139 |
140 | /* ICMP Remaining packet size = IP Length - (ICMP type+code+checksum size) */
141 | icmp_remaining_size = ip_packet_length - (ip_header_size + 4);
142 |
143 | ether_sum_words(&sum, &icmp->id, icmp_remaining_size);
144 |
145 | /* Get checksum */
146 | icmp->checksum = ether_get_checksum(sum);
147 |
148 | /* Send ICMP response packet(uses callback) */
149 | ether_send_data(ethernet, (uint8_t*)ethernet->ether_obj, ip_packet_length + ETHER_FRAME_SIZE);
150 |
151 | }
152 | else
153 | {
154 | func_retval = NET_ICMP_RESP_IGNORE;
155 | }
156 |
157 | }
158 |
159 | return func_retval;
160 | }
161 |
162 |
163 |
164 |
165 |
166 | /*****************************************************************
167 | * @brief Function to send ICMP request
168 | * @param *ethernet : Reference to the Ethernet structure
169 | * @param icmp_type : ICMP request type
170 | * @param *destination_ip : Destination IP address
171 | * @param sequence_no : ICMP packet sequence Number
172 | * @param *destination_mac : Destination MAC address
173 | * @param *source_mac : Source MAC address
174 | * @retval int8_t : Error = -8, Success = 0.
175 | ****************************************************************/
176 | int8_t ether_send_icmp_req(ethernet_handle_t *ethernet, icmp_type_t icmp_type, uint8_t *destination_ip,
177 | uint8_t *sequence_no, uint8_t* destination_mac, uint8_t *source_mac)
178 | {
179 | int8_t func_retval = 0;
180 |
181 | net_ip_t *ip;
182 | net_icmp_t *icmp;
183 |
184 | uint32_t sum = 0;
185 | uint16_t icmp_packet_size = 0;
186 | uint16_t ip_id = 0;
187 |
188 | if(ethernet->ether_obj == NULL)
189 | {
190 | func_retval = NET_ICMP_REQ_ERROR;
191 | }
192 | else
193 | {
194 |
195 | /* Fill ICMP frame */
196 | ip = (void*)ðernet->ether_obj->data;
197 |
198 | icmp = (void*)( (uint8_t*)ip + IP_HEADER_SIZE );
199 |
200 | icmp->type = ICMP_ECHOREQUEST;
201 |
202 | icmp->code = 0;
203 |
204 | /* Currently fixed */
205 | icmp->id = 15625;
206 |
207 | icmp->sequence_no = htons(*sequence_no);
208 |
209 | (*sequence_no)++;
210 |
211 | /* Calculate ICMP checksum */
212 | sum = 0;
213 | ether_sum_words(&sum, &icmp->type, 2);
214 |
215 | ether_sum_words(&sum, &icmp->id, 5);
216 |
217 | icmp->checksum = ether_get_checksum(sum);
218 |
219 | icmp_packet_size = ICMP_FRAME_SIZE;
220 |
221 |
222 | /* Fill IP frame */
223 | fill_ip_frame(ip, &ip_id, destination_ip, ethernet->host_ip, IP_ICMP, icmp_packet_size);
224 |
225 |
226 | /* Fill Ethernet frame */
227 | fill_ether_frame(ethernet, destination_mac, source_mac, ETHER_IPV4);
228 |
229 |
230 | /* Send ICMP data */
231 | ether_send_data(ethernet, (uint8_t*)ethernet->ether_obj, ETHER_FRAME_SIZE + htons(ip->total_length));
232 |
233 | }
234 |
235 |
236 | return func_retval;
237 | }
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
--------------------------------------------------------------------------------
/NET_API/src/ipv4.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file ipv4.c
4 | * @author Aditya Mall,
5 | * @brief IP version 4 protocol source file
6 | *
7 | * Info
8 | *
9 | ******************************************************************************
10 | * @attention
11 | *
12 | * © COPYRIGHT(c) 2019 Aditya Mall, MIT License
13 | *
14 | * MIT License
15 | *
16 | * Copyright (c) 2019 Aditya Mall
17 | *
18 | * Permission is hereby granted, free of charge, to any person obtaining a copy
19 | * of this software and associated documentation files (the "Software"), to deal
20 | * in the Software without restriction, including without limitation the rights
21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | * copies of the Software, and to permit persons to whom the Software is
23 | * furnished to do so, subject to the following conditions:
24 | *
25 | * The above copyright notice and this permission notice shall be included in all
26 | * copies or substantial portions of the Software.
27 | *
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | ******************************************************************************
40 | */
41 |
42 |
43 | /*
44 | * Standard header and api header files
45 | */
46 | #include
47 |
48 | #include "ipv4.h"
49 |
50 | #include "network_utilities.h"
51 |
52 |
53 |
54 | /******************************************************************************/
55 | /* */
56 | /* Data Structures and Defines */
57 | /* */
58 | /******************************************************************************/
59 |
60 |
61 |
62 |
63 |
64 | /******************************************************************************/
65 | /* */
66 | /* IPV4 Functions */
67 | /* */
68 | /******************************************************************************/
69 |
70 |
71 |
72 | /**************************************************************
73 | * @brief Function to get IP data for current host device
74 | * validates IP Checksum, (Only handles UNICAST)
75 | * @param *ethernet : reference to the Ethernet handle
76 | * @retval int16_t : Error = -4, -5,
77 | * Success = 1 (UNICAST),
78 | * = 2 (BROADCAST)
79 | **************************************************************/
80 | int16_t get_ip_communication_type(ethernet_handle_t *ethernet)
81 | {
82 | int16_t func_retval = 0;
83 |
84 | net_ip_t *ip;
85 |
86 | uint32_t sum = 0;
87 |
88 | if(ethernet->ether_obj == NULL)
89 | {
90 | func_retval = NET_IP_GET_ERROR;
91 | }
92 | else
93 | {
94 | ip = (void*)ðernet->ether_obj->data;
95 |
96 | /* Validate IP header checksum */
97 | ether_sum_words(&sum, ip, (ip->version_length.header_length) * 4);
98 |
99 | if( (ether_get_checksum(sum) == 0) )
100 | {
101 | /* Check if UNICAST (temporarily make UNICAST unaccessible when requesting IP through DHCP, dynamic IP) */
102 | /* mode_dhcp_req bit is cleared by DHCP state machine, done for better throughput during requesting. */
103 | if( (strncmp((char*)ip->destination_ip, (char*)ethernet->host_ip, 4) == 0) && ethernet->status.mode_dhcp_init != 1 )
104 | {
105 | func_retval = 1;
106 | }
107 | /* Check if BROADCAST */
108 | else if( strncmp((char*)ip->destination_ip, (char*)ethernet->broadcast_ip, 4) == 0 )
109 | {
110 | func_retval = 2;
111 | }
112 |
113 | }
114 | else
115 | {
116 | func_retval = NET_IP_CHECKSUM_ERROR;
117 | }
118 |
119 | }
120 |
121 | return func_retval;
122 | }
123 |
124 |
125 |
126 | /****************************************************************
127 | * @brief Function to get IP protocol type
128 | * @param *ethernet : reference to the Ethernet handle
129 | * @retval int16_t : Error = -4, -5, Success = protocol type
130 | ***************************************************************/
131 | ip_protocol_type_t get_ip_protocol_type(ethernet_handle_t *ethernet)
132 | {
133 | ip_protocol_type_t protocol;
134 |
135 | net_ip_t *ip;
136 |
137 | ip = (void*)ðernet->ether_obj->data;
138 |
139 | protocol = (ip_protocol_type_t)ip->protocol;
140 |
141 | return protocol;
142 | }
143 |
144 |
145 |
146 | /**********************************************************
147 | * @brief Function to fill the IP frame
148 | * @param *ip : reference to the IP structure
149 | * @param *id : reference to IP identifier
150 | * @param *destination_ip : destination IP address
151 | * @param *source_ip : source IP address
152 | * @param protocol : IP protocol type
153 | * @param data_size : size of payload
154 | * @retval int8_t : Error = NULL
155 | **********************************************************/
156 | int8_t fill_ip_frame(net_ip_t *ip, uint16_t *id, uint8_t *destination_ip, uint8_t *source_ip, ip_protocol_type_t protocol, uint16_t data_size)
157 | {
158 | int8_t func_retval = 0;
159 |
160 | uint8_t i = 0;
161 |
162 | uint32_t sum = 0;
163 |
164 | if(ip == NULL || destination_ip == NULL || source_ip == NULL || data_size == 0 || data_size > UINT16_MAX)
165 | {
166 | func_retval = -1;
167 | }
168 | else
169 | {
170 |
171 | ip->version_length.version = IP_VERSION;
172 | ip->version_length.header_length = IP_HEADER_LENGTH;
173 |
174 | ip->service_type = 0;
175 |
176 | /* Get identifier and increment it for next message */
177 | ip->id = htons(*id);
178 |
179 | (*id)++;
180 |
181 | /* Don't Fragment set condition */
182 | ip->flags_offset = htons(IP_DF_SET);
183 |
184 | ip->ttl = IP_TTL_VALUE;
185 |
186 | ip->protocol = protocol;
187 |
188 | ip->total_length = htons(IP_HEADER_SIZE + data_size);
189 |
190 | for(i=0; i < 4; i++)
191 | {
192 | ip->destination_ip[i] = destination_ip[i];
193 | ip->source_ip[i] = source_ip[i];
194 | }
195 |
196 | /* Calculate checksum */
197 | sum = 0;
198 | ether_sum_words(&sum, &ip->version_length, 10);
199 |
200 | ether_sum_words(&sum, ip->source_ip, 8);
201 |
202 | ip->header_checksum = ether_get_checksum(sum);
203 | }
204 |
205 |
206 | return func_retval;
207 | }
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
--------------------------------------------------------------------------------
/NET_API/src/network_utilities.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file network_utilities.c
4 | * @author Aditya Mall,
5 | * @brief Network utility source file
6 | *
7 | * Info
8 | *
9 | ******************************************************************************
10 | * @attention
11 | *
12 | * © COPYRIGHT(c) 2019 Aditya Mall, MIT License
13 | *
14 | * MIT License
15 | *
16 | * Copyright (c) 2019 Aditya Mall
17 | *
18 | * Permission is hereby granted, free of charge, to any person obtaining a copy
19 | * of this software and associated documentation files (the "Software"), to deal
20 | * in the Software without restriction, including without limitation the rights
21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | * copies of the Software, and to permit persons to whom the Software is
23 | * furnished to do so, subject to the following conditions:
24 | *
25 | * The above copyright notice and this permission notice shall be included in all
26 | * copies or substantial portions of the Software.
27 | *
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | ******************************************************************************
40 | */
41 |
42 |
43 |
44 | /*
45 | * Standard header and api header files
46 | */
47 | #include
48 | #include
49 | #include
50 |
51 | #include "network_utilities.h"
52 |
53 |
54 |
55 | /******************************************************************************/
56 | /* */
57 | /* Private Functions */
58 | /* */
59 | /******************************************************************************/
60 |
61 |
62 | /* Implementation of glibc reentrant strtok Copyright (C) 1991-2019 GNU C Library */
63 |
64 | static char *api_strtok_r (char *s, const char *delim, char **save_ptr)
65 | {
66 | char *end;
67 | if (s == NULL)
68 | s = *save_ptr;
69 | if (*s == '\0')
70 | {
71 | *save_ptr = s;
72 | return NULL;
73 | }
74 | /* Scan leading delimiters. */
75 | s += strspn (s, delim);
76 | if (*s == '\0')
77 | {
78 | *save_ptr = s;
79 | return NULL;
80 | }
81 | /* Find the end of the token. */
82 | end = s + strcspn (s, delim);
83 | if (*end == '\0')
84 | {
85 | *save_ptr = end;
86 | return s;
87 | }
88 | /* Terminate the token and make *SAVE_PTR point past it. */
89 | *end = '\0';
90 | *save_ptr = end + 1;
91 | return s;
92 | }
93 |
94 |
95 |
96 |
97 | /******************************************************************************/
98 | /* */
99 | /* Network Utility Functions */
100 | /* */
101 | /******************************************************************************/
102 |
103 |
104 |
105 | /************************************************************************
106 | * @brief Function to convert from host to network order and vice versa
107 | * (For 16 bit data)
108 | * @retval uint16_t : host to network or network to host converted data
109 | ************************************************************************/
110 | uint16_t htons(uint16_t value)
111 | {
112 | /* Ignore byte swap for 8 bit variables */
113 | if((value << 8) == 0)
114 | return value;
115 | else
116 | return ((value & 0xFF00) >> 8) + ((value & 0x00FF) << 8);
117 | }
118 |
119 |
120 |
121 |
122 | /************************************************************************
123 | * @brief Function to convert from host to network order and vice versa
124 | * (For 32 bit data)
125 | * Copyright (C) 1997-2019 Free Software Foundation, Inc.
126 | *
127 | * @retval uint32_t : host to network or network to host converted data
128 | ************************************************************************/
129 |
130 |
131 | /* Swap bytes in 32-bit value. */
132 | #define __bswap_constant_32(x) \
133 | ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) \
134 | | (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24))
135 |
136 |
137 | uint32_t htonl(uint32_t x)
138 | {
139 | return (uint32_t)__bswap_constant_32 (x);
140 | }
141 |
142 |
143 |
144 |
145 |
146 |
147 | /********************************************************
148 | * @brief Function to set mac address
149 | * @param *device_mac : device mac address (Hex)
150 | * @param *mac_address : mac address (string)
151 | * @retval int8_t : Error = -1, Success = 0
152 | ********************************************************/
153 | int8_t set_mac_address(uint8_t *device_mac, char *mac_address)
154 | {
155 | int8_t func_retval = 0;
156 |
157 | char mac_address_copy[18] = {0}; /*!< Copy variable */
158 | char *rest_ptr; /*!< Tracking pointer */
159 | char *token; /*!< token */
160 |
161 |
162 | /* Copy mac address to copy variable for null termination (required for string function) */
163 | strncpy(mac_address_copy, mac_address, 18); /* Size of mac address entered as string with null at index 18 */
164 |
165 | uint8_t index = 0;
166 |
167 | if(mac_address_copy[17] != 0)
168 | {
169 | func_retval = -1;
170 | }
171 | else
172 | {
173 | rest_ptr = mac_address_copy;
174 |
175 | /* strtok_r function for non glibc compliant code */
176 | while( (token = api_strtok_r(rest_ptr, ":", &rest_ptr)) )
177 | {
178 | /* Convert to hex */
179 | device_mac[index] = strtol(token, NULL, 16);
180 |
181 | index++;
182 | }
183 |
184 | }
185 |
186 |
187 | return func_retval;
188 | }
189 |
190 |
191 |
192 | /********************************************************
193 | * @brief function to set ip address
194 | * @param *host_ip : host ip address (integer)
195 | * @param *ip_address : ip address (string)
196 | * @retval int8_t : Error = -1, Success = 0
197 | ********************************************************/
198 | int8_t set_ip_address(uint8_t *host_ip, char *ip_address)
199 | {
200 |
201 | int8_t func_retval = 0;
202 |
203 | char ip_address_copy[16] = {0}; /*!< Copy variable */
204 | char *rest_ptr; /*!< Tracking pointer */
205 | char *token; /*!< token */
206 |
207 |
208 | /* Copy ip address to copy variable for null termination (required for string function) */
209 | strncpy(ip_address_copy, ip_address, 16); /* Size of ip address entered as string with null at index 18 */
210 |
211 | uint8_t index = 0;
212 |
213 | if(ip_address_copy[15] != 0)
214 | {
215 | func_retval = -1;
216 | }
217 | else
218 | {
219 | rest_ptr = ip_address_copy;
220 |
221 | /* strtok_r function for non glibc compliant code */
222 | while( (token = api_strtok_r(rest_ptr, ".", &rest_ptr)) )
223 | {
224 | /* Convert to hex */
225 | host_ip[index] = strtol(token, NULL, 10);
226 |
227 | index++;
228 | }
229 |
230 | }
231 |
232 | return func_retval;
233 |
234 |
235 | }
236 |
237 |
238 |
239 | /***********************************************
240 | * @brief Function to swap network address
241 | * (used in response messages)
242 | * @param *l_address : address value LHS
243 | * @param *r_address : address value RHS
244 | * @param size : size of address
245 | * @retval int8_t : Error = -1, Success = 0
246 | ***********************************************/
247 | int8_t net_swap_address(uint8_t* l_address, uint8_t *r_address, uint8_t size)
248 | {
249 | int8_t func_retval = 0;
250 | int8_t index = 0;
251 |
252 | if(l_address == NULL || r_address == NULL || size == 0 || size > 6)
253 | {
254 | func_retval = -1;
255 | }
256 | else
257 | {
258 | for(index = 0; index < size; index++)
259 | {
260 | l_address[index] = l_address[index] ^ r_address[index];
261 | r_address[index] = l_address[index] ^ r_address[index];
262 | l_address[index] = l_address[index] ^ r_address[index];
263 | }
264 |
265 | }
266 |
267 | return func_retval;
268 | }
269 |
270 |
271 |
272 |
273 |
274 | /*********************************************************
275 | * @brief Function to set broadcast address
276 | * @param *destination_address : destination address
277 | * @param size : size of address
278 | * @retval int8_t : Error = -1, Success = 0
279 | *********************************************************/
280 | int8_t set_broadcast_address(uint8_t *destination_address, uint8_t size)
281 | {
282 | int8_t func_retval = 0;
283 | int8_t index = 0;
284 |
285 | if(destination_address == NULL || size == 0)
286 | {
287 | func_retval = -1;
288 | }
289 | else
290 | {
291 | switch(size)
292 | {
293 |
294 | case 4: /* For IP address length */
295 |
296 | for(index = 0; index < 4; index++)
297 | {
298 | destination_address[index] = 0xFF;
299 | }
300 |
301 | break;
302 |
303 |
304 | case 6: /* For MAC address length */
305 |
306 | for(index = 0; index < 6; index++)
307 | {
308 | destination_address[index] = 0xFF;
309 | }
310 |
311 | break;
312 |
313 |
314 | default:
315 |
316 | func_retval = -1;
317 |
318 | break;
319 | }
320 |
321 | }
322 |
323 | return func_retval;
324 | }
325 |
326 |
327 |
328 |
329 |
330 |
--------------------------------------------------------------------------------
/NET_API/src/udp.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file udp.c
4 | * @author Aditya Mall,
5 | * @brief UDP protocol source file
6 | *
7 | * Info
8 | *
9 | ******************************************************************************
10 | * @attention
11 | *
12 | * © COPYRIGHT(c) 2019 Aditya Mall, MIT License
13 | *
14 | * MIT License
15 | *
16 | * Copyright (c) 2019 Aditya Mall
17 | *
18 | * Permission is hereby granted, free of charge, to any person obtaining a copy
19 | * of this software and associated documentation files (the "Software"), to deal
20 | * in the Software without restriction, including without limitation the rights
21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 | * copies of the Software, and to permit persons to whom the Software is
23 | * furnished to do so, subject to the following conditions:
24 | *
25 | * The above copyright notice and this permission notice shall be included in all
26 | * copies or substantial portions of the Software.
27 | *
28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 | *
39 | ******************************************************************************
40 | */
41 |
42 |
43 |
44 | /*
45 | * Standard header and api header files
46 | */
47 | #include
48 |
49 | #include "ipv4.h"
50 | #include "udp.h"
51 | #include "arp.h"
52 |
53 | #include "network_utilities.h"
54 |
55 |
56 |
57 |
58 | /******************************************************************************/
59 | /* */
60 | /* Data Structures and Defines */
61 | /* */
62 | /******************************************************************************/
63 |
64 |
65 | #define UDP_FRAME_SIZE 8
66 |
67 | #pragma pack(1)
68 |
69 | /* UDP Frame (8 Bytes) */
70 | typedef struct _net_udp
71 | {
72 | uint16_t source_port; /*!< UDP source port */
73 | uint16_t destination_port; /*!< UDP destination port */
74 | uint16_t length; /*!< UDP packet length */
75 | uint16_t checksum; /*!< UDP checksum (pseudo header + packet) */
76 | uint8_t data; /*!< UDP data */
77 |
78 | }net_udp_t;
79 |
80 |
81 |
82 | /******************************************************************************/
83 | /* */
84 | /* Private Functions */
85 | /* */
86 | /******************************************************************************/
87 |
88 |
89 |
90 | /*******************************************************
91 | * @brief Static function to validate UDP checksum
92 | * @param *ip : Reference to IP frame structure
93 | * @param *udp : Reference to UDP frame structure
94 | * @retval uint8_t : Error = 0, Success = 1
95 | ******************************************************/
96 | static uint8_t validate_udp_checksum(net_ip_t *ip, net_udp_t *udp)
97 | {
98 | uint8_t func_retval = 0;
99 |
100 | uint32_t sum = 0;
101 | uint16_t pseudo_protocol = 0;
102 |
103 | if(ip == NULL || udp == NULL)
104 | {
105 | func_retval = 0;
106 | }
107 | else
108 | {
109 |
110 | /* validate UDP checksum */
111 | sum = 0;
112 |
113 | ether_sum_words(&sum, &ip->source_ip, 8);
114 |
115 | pseudo_protocol = ip->protocol;
116 |
117 | sum += ( (pseudo_protocol & 0xFF) << 8 );
118 |
119 | ether_sum_words(&sum, &udp->length, 2);
120 |
121 | ether_sum_words(&sum, udp, ntohs(udp->length));
122 |
123 | func_retval = (ether_get_checksum(sum) == 0);
124 | }
125 |
126 | return func_retval;
127 | }
128 |
129 |
130 |
131 |
132 | /**************************************************************
133 | * @brief Function get calculate UDP checksum
134 | * (UDP Headers + UDP data)
135 | * @param *ip : Reference to IP frame structure
136 | * @param *udp : Reference to UDP frame structure
137 | * @param data_length : Length of UDP data
138 | * @retval uint8_t : Error = 0, Success = checksum value
139 | **************************************************************/
140 | static uint16_t get_udp_checksum(net_ip_t *ip, net_udp_t *udp, uint16_t data_length)
141 | {
142 |
143 | uint16_t func_retval = 0;
144 | uint32_t sum = 0;
145 | uint16_t pseudo_protocol = 0;
146 |
147 | if(ip == NULL || udp == NULL)
148 | {
149 | func_retval = 0;
150 | }
151 | else
152 | {
153 |
154 | /* UDP Pseudo Header checksum calculation */
155 | sum = 0;
156 |
157 | ether_sum_words(&sum, ip->source_ip, 8);
158 |
159 | pseudo_protocol = ip->protocol;
160 |
161 | /* create space for reserved bits */
162 | sum += ( (pseudo_protocol & 0xFF) << 8 );
163 |
164 | ether_sum_words(&sum, &udp->length, 2);
165 |
166 | /* UDP Fixed header checksum calculation, excluding checksum field */
167 | ether_sum_words(&sum, udp, UDP_FRAME_SIZE - 2);
168 |
169 | /* Add UPD data sum */
170 | ether_sum_words(&sum, &udp->data, data_length);
171 |
172 | func_retval = ether_get_checksum(sum);
173 | }
174 |
175 | return func_retval;
176 |
177 | }
178 |
179 |
180 |
181 | /******************************************************************************/
182 | /* */
183 | /* UDP Functions */
184 | /* */
185 | /******************************************************************************/
186 |
187 |
188 |
189 |
190 |
191 | /*****************************************************************
192 | * @brief Function to get UDP data inside network state machine
193 | * @param *ethernet : Reference to the Ethernet handle
194 | * @param *data : UDP data
195 | * @param data_length : Length of UDP data
196 | * @retval uint8_t : Error = 0, Success = 1
197 | *****************************************************************/
198 | uint8_t ether_get_udp_data(ethernet_handle_t *ethernet, uint8_t *data, uint16_t data_length)
199 | {
200 | uint8_t func_retval = 0;
201 |
202 | net_ip_t *ip;
203 | net_udp_t *udp;
204 |
205 | uint8_t validate = 0;
206 |
207 | uint16_t udp_packet_length = 0;
208 | uint16_t udp_data_length = 0;
209 |
210 | ip = (void*)ðernet->ether_obj->data;
211 |
212 | udp = (void*)( (uint8_t*)ip + IP_HEADER_SIZE );
213 |
214 |
215 | if(ethernet->ether_obj == NULL || data == NULL)
216 | {
217 | func_retval = 0;
218 | }
219 | else
220 | {
221 | udp_packet_length = ntohs(udp->length);
222 | udp_data_length = udp_packet_length - UDP_FRAME_SIZE;
223 |
224 | /* Check and Truncate UDP data length */
225 | if(data_length > udp_data_length)
226 | data_length = udp_data_length;
227 |
228 | /* validate UDP checksum */
229 | validate = validate_udp_checksum(ip, udp);
230 |
231 | /* Get UDP data */
232 | if(validate)
233 | {
234 | memcpy((char*)data, (char*)&udp->data, data_length);
235 | }
236 |
237 | func_retval = validate;
238 | }
239 |
240 |
241 | return func_retval;
242 | }
243 |
244 |
245 |
246 |
247 |
248 | /*******************************************************************
249 | * @brief Raw Function to send UPD packets
250 | * UDP data dependent upon total data allocated to
251 | * ethernet object
252 | * @param *ethernet : Reference to the Ethernet handle
253 | * @param *source_addr : Reference to source address structure
254 | * @param *destination_ip : Destination IP address
255 | * @param *destination_mac : Destination MAC address
256 | * @param destination_port : UDP destination port
257 | * @param *data : UDP data
258 | * @param data_length : Length of UDP data
259 | * @retval int8_t : Error = -9, Success = 0
260 | *******************************************************************/
261 | int8_t ether_send_udp_raw(ethernet_handle_t *ethernet, ether_source_t *source_addr, uint8_t *destination_ip,
262 | uint8_t *destination_mac, uint16_t destination_port, uint8_t *data, uint16_t data_length)
263 | {
264 |
265 | int8_t func_retval = 0;
266 |
267 | net_ip_t *ip;
268 | net_udp_t *udp;
269 |
270 | uint16_t index = 0;
271 |
272 | uint8_t *data_copy;
273 | uint16_t udp_packet_size = 0;
274 |
275 |
276 | if(ethernet->ether_obj == NULL || source_addr == NULL || destination_ip == NULL || destination_mac == NULL \
277 | || destination_port == 0 || data == NULL || data_length == 0 || data_length > UINT16_MAX)
278 | {
279 | func_retval = NET_UDP_RAW_SEND_ERROR;
280 | }
281 | else
282 | {
283 |
284 | ip = (void*)ðernet->ether_obj->data;
285 |
286 | udp = (void*)( (uint8_t*)ip + IP_HEADER_SIZE );
287 |
288 |
289 | /* Fill UDP frame */
290 | udp->source_port = htons(source_addr->source_port);
291 | udp->destination_port = htons(destination_port);
292 |
293 | udp->length = htons(UDP_FRAME_SIZE + data_length);
294 |
295 |
296 | /* Add UDP data */
297 | data_copy = &udp->data;
298 |
299 | for(index = 0; index < data_length; index++)
300 | {
301 | data_copy[index] = data[index];
302 | }
303 |
304 |
305 | /* Fill IP frame before UDP checksum calculation */
306 | udp_packet_size = UDP_FRAME_SIZE + data_length;
307 |
308 | fill_ip_frame(ip, &source_addr->identifier, destination_ip, source_addr->source_ip, IP_UDP, udp_packet_size);
309 |
310 |
311 | /* get UDP checksum */
312 | udp->checksum = get_udp_checksum(ip, udp, data_length);
313 |
314 |
315 | /* Fill Ethernet frame */
316 | fill_ether_frame(ethernet, destination_mac, source_addr->source_mac, ETHER_IPV4);
317 |
318 |
319 | /* Send UPD data */
320 | ether_send_data(ethernet,(uint8_t*)ethernet->ether_obj, ETHER_FRAME_SIZE + htons(ip->total_length));
321 | }
322 |
323 | return func_retval;
324 | }
325 |
326 |
327 |
328 |
329 |
330 | /****************************************************************
331 | * @brief Function detect UDP packet, state machine independent
332 | * @param *ethernet : Reference to the Ethernet handle
333 | * @param *network_data : network data from PHY
334 | * @param network_data_length : network data length to be read
335 | * @retval uint8_t : Error = 0,
336 | * Success = 1 (UNICAST)
337 | * = 2 (BROADCAST)
338 | ****************************************************************/
339 | uint8_t ether_is_udp(ethernet_handle_t *ethernet, uint8_t *network_data, uint16_t network_data_length)
340 | {
341 | uint8_t func_retval = 0;
342 | uint8_t block_loop = 0;
343 |
344 | int16_t comm_type = 0;
345 |
346 | if(ethernet->ether_obj == NULL || network_data == NULL || network_data_length == 0 || network_data_length > UINT16_MAX)
347 | {
348 | func_retval = 0;
349 | }
350 | else
351 | {
352 | /* Wait for data */
353 | block_loop = ethernet->status.mode_read_blocking;
354 |
355 | do
356 | {
357 | if(ether_get_data(ethernet, network_data, network_data_length))
358 | {
359 | /* Check if protocol is IPV4 */
360 | if(get_ether_protocol_type(ethernet) == ETHER_IPV4)
361 | {
362 |
363 | /* Checks if UNICAST, validates checksum */
364 | comm_type = get_ip_communication_type(ethernet);
365 |
366 | /* UNICAST */
367 | if(comm_type == 1)
368 | {
369 | /* Check if protocol is UDP */
370 | if(get_ip_protocol_type(ethernet) == IP_UDP)
371 | {
372 | func_retval = 1;
373 |
374 | break;
375 | }
376 |
377 | }
378 | /* BROADCAST */
379 | else if(comm_type == 2)
380 | {
381 | /* Check if protocol is UDP */
382 | if(get_ip_protocol_type(ethernet) == IP_UDP)
383 | {
384 | func_retval = 2;
385 |
386 | break;
387 | }
388 |
389 |
390 | }
391 |
392 | }
393 |
394 | }
395 |
396 | }while(block_loop);
397 |
398 | }
399 |
400 | return func_retval;
401 | }
402 |
403 |
404 |
405 |
406 |
407 | /*****************************************************************
408 | * @brief Function to read UPD packets
409 | * @param *ethernet : Reference to the Ethernet handle
410 | * @param *network_data : network data from PHY
411 | * @param *application_data : UDP data
412 | * @param app_data_length : Length of UDP data
413 | * @retval int8_t : Error = 0, Success = 1
414 | *****************************************************************/
415 | uint8_t ether_read_udp(ethernet_handle_t *ethernet, uint8_t *network_data, char *application_data, uint16_t app_data_length)
416 | {
417 | uint8_t func_retval = 0;
418 | uint8_t api_retval = 0;
419 |
420 |
421 | if(ethernet->ether_obj == NULL || network_data == NULL || app_data_length == 0 || app_data_length > UINT16_MAX)
422 | {
423 | func_retval = 0;
424 | }
425 | else
426 | {
427 | api_retval = ether_is_udp(ethernet, network_data, ETHER_MTU_SIZE);
428 |
429 | if(api_retval)
430 | {
431 | func_retval = ether_get_udp_data(ethernet, (uint8_t*)application_data, app_data_length);
432 |
433 | }
434 | }
435 |
436 | return func_retval;
437 | }
438 |
439 |
440 |
441 |
442 | /**************************************************************
443 | * @brief Function to send UPD packets
444 | * UDP data dependent upon total data allocated to
445 | * ethernet object
446 | * @param *ethernet : Reference to the Ethernet handle
447 | * @param *destination_ip : Destination IP address
448 | * @param destination_port : UDP destination port
449 | * @param *application_data : UDP data
450 | * @param data_length : Length of UDP data
451 | * @retval int8_t : Error = -10, Success = 0
452 | **************************************************************/
453 | int8_t ether_send_udp(ethernet_handle_t *ethernet, uint8_t *destination_ip, uint16_t destination_port, char *application_data, uint16_t data_length)
454 | {
455 |
456 | int8_t func_retval = 0;
457 |
458 | net_ip_t *ip;
459 | net_udp_t *udp;
460 |
461 | /* UDP related variables */
462 | uint16_t index = 0;
463 | uint8_t *data_copy;
464 | uint16_t udp_packet_size = 0;
465 |
466 | /*IP related variables */
467 | uint16_t ip_identfier = 0;
468 |
469 | /* Ethernet Frame related variables */
470 | uint8_t destination_mac[ETHER_MAC_SIZE] = {0};
471 |
472 |
473 | if(ethernet->ether_obj == NULL || destination_ip == NULL || destination_port == 0 \
474 | || application_data == NULL || data_length == 0 || data_length > UINT16_MAX)
475 | {
476 | func_retval = NET_UDP_SEND_ERROR;
477 | }
478 | else
479 | {
480 |
481 | ip = (void*)ðernet->ether_obj->data;
482 |
483 | udp = (void*)( (uint8_t*)ip + IP_HEADER_SIZE );
484 |
485 |
486 | /* Fill UDP frame */
487 | udp->source_port = htons(ethernet->source_port);
488 | udp->destination_port = htons(destination_port);
489 |
490 | udp->length = htons(UDP_FRAME_SIZE + data_length);
491 |
492 |
493 | /* Add UDP data */
494 | data_copy = &udp->data;
495 |
496 | for(index = 0; index < data_length; index++)
497 | {
498 | data_copy[index] = application_data[index];
499 | }
500 |
501 |
502 | /* Fill IP frame */
503 | ip_identfier = get_unique_id(ethernet, 2000);
504 |
505 | udp_packet_size = UDP_FRAME_SIZE + data_length;
506 |
507 | fill_ip_frame(ip, &ip_identfier, destination_ip, ethernet->host_ip, IP_UDP, udp_packet_size);
508 |
509 |
510 | /* get UDP checksum */
511 | udp->checksum = get_udp_checksum(ip, udp, data_length);
512 |
513 |
514 | /* Get MAC address from ARP table */
515 | ether_arp_resolve_address(ethernet, destination_mac, destination_ip);
516 |
517 | /* Fill Ethernet frame */
518 | fill_ether_frame(ethernet, destination_mac, ethernet->host_mac, ETHER_IPV4);
519 |
520 |
521 | /* Send UPD data */
522 | ether_send_data(ethernet,(uint8_t*)ethernet->ether_obj, ETHER_FRAME_SIZE + htons(ip->total_length));
523 |
524 | }
525 |
526 | return func_retval;
527 |
528 |
529 | }
530 |
531 |
532 |
533 |
534 | /**************************************************************
535 | * @brief Function to read UDP packet
536 | * @param *ethernet : reference to the Ethernet handle
537 | * @param *network_data : network data from the ether PHY
538 | * @param net_data_length : network data length
539 | * @param *source_port : UDP source port
540 | * @param *destination_port : UDP destination port
541 | * @param *application_data : UDP data
542 | * @param data_length : Length of UDP data
543 | * @param app_data_length :
544 | * @retval uint16_t : Error = 0, Success = bytes read
545 | **************************************************************/
546 | uint16_t ether_read_udp_raw(ethernet_handle_t *ethernet, uint8_t *network_data, uint16_t net_data_length,
547 | uint16_t *source_port, uint16_t *destination_port, char *application_data, uint16_t app_data_length)
548 | {
549 | uint16_t func_retval = 0;
550 |
551 | net_ip_t *ip;
552 | net_udp_t *udp;
553 |
554 | uint8_t api_retval = 0;
555 | uint8_t validate = 0;
556 |
557 | uint16_t udp_packet_length = 0;
558 | uint16_t udp_data_length = 0;
559 |
560 |
561 | if(ethernet->ether_obj == NULL || network_data == NULL || net_data_length == 0 || net_data_length > UINT16_MAX)
562 | {
563 | func_retval = 0;
564 | }
565 | else
566 | {
567 | api_retval = ether_is_udp(ethernet, network_data, net_data_length);
568 |
569 | if(api_retval)
570 | {
571 | ip = (void*)ðernet->ether_obj->data;
572 |
573 | udp = (void*)( (uint8_t*)ip + IP_HEADER_SIZE );
574 |
575 | /* get source and destination port */
576 | *source_port = ntohs(udp->source_port);
577 | *destination_port = ntohs(udp->destination_port);
578 |
579 | /* Get UDP packet length and data length from header */
580 | udp_packet_length = ntohs(udp->length);
581 | udp_data_length = udp_packet_length - UDP_FRAME_SIZE;
582 |
583 | /* Check and Truncate UDP data length */
584 | if(app_data_length > udp_data_length)
585 | app_data_length = udp_data_length;
586 |
587 | /* validate UDP checksum */
588 | validate = validate_udp_checksum(ip, udp);
589 |
590 | /* Get UDP header */
591 | if(validate)
592 | {
593 | memcpy((char*)application_data, (char*)&udp->data, app_data_length);
594 |
595 | func_retval = app_data_length;
596 | }
597 |
598 | }
599 | }
600 |
601 | return func_retval;
602 | }
603 |
604 |
605 |
606 |
607 |
608 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Minimal-TCP-IP-Stack
2 |
3 | ### Minimal-TCP/IP stack for enc28j60 module.
4 |
5 | 
6 | 
7 | 
8 |
9 | 
10 |
11 |
12 |
13 | ## Description
14 | **minimal-TCP/IP stack** is a portable network stack API using the enc28j60 ethernet module on ARM-cortex M4 architecture based board for non OS enviornment. Tested on (Texas Instruments TM4c123gh series processor), developed as a part of course projects (EE6314) at the University of Texas at Arlington. This API was used to provide a network layer interface for the home automation project and MQTT gateway project for low power sensor network.
15 |
16 |
17 | ## Features
18 |
19 | ##### Current:-
20 | * Simple and easy to use API.
21 | * Implements Ethernet layer, ARP, ICMP, TCP and UDP protocols.
22 | * Supports Dynamic IP through DHCP.
23 | * API based layers for raw TCP and UDP sockets.
24 | * Supports max MTU of 1500 bytes.
25 | * Lightweight stack usage of approximate 4096 bytes for medium scale MCU based embedded systems.
26 | * Portable, can be ported to other platforms.
27 | * Extensively tested as TCP and UDP clients and also as clients with application layer protocols like MQTT.
28 |
29 | ##### Future Version:-
30 | * Linux Sockets like API.
31 | * Support for multiple sockets.
32 | * RTOS based testing and support.
33 |
34 | ## Testing
35 |
36 | **The API is tested on TIVA Launcpad by Texas Instruments and enc28j60 module.**
37 |
38 |
39 | ##### Hardware Configuration
40 |
41 | ENC28J60 Ethernet controller connected on the following pins :-
42 | * MOSI (SSI2Tx) on PB7
43 | * MISO (SSI2Rx) on PB6
44 | * SCLK (SSI2Clk) on PB4
45 | * ~CS (GPIO) on PB1
46 |
47 | ##### Dependencies
48 |
49 | Test code is dependent on the following APIs:-
50 | * Clone "clterm" Repo from : https://github.com/adimalla/clTerm
51 | * Clone "MQTT-3.1-C" Repo from : https://github.com/adimalla/MQTT-3.1-C
52 |
53 |
54 | ## Disclaimer
55 | If you are a student at The University of Texas at Arlington, please take prior permissions from Dr.Jason Losh and author of this repository before using any part of the source code in your project, in order to abide by the academic integrity of the university.
56 |
57 | ## Contact
58 |
59 | * aditya.mall1990@gmail.com
60 | * aditya.mall@mavs.uta.edu
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/enc28j60.c:
--------------------------------------------------------------------------------
1 | // ENC28J60 Driver
2 | // Author: Jason Losh
3 | // Modifications: Aditya Mall
4 | // The University of Texas at Arlington
5 |
6 | //-----------------------------------------------------------------------------
7 | // Hardware Target
8 | //-----------------------------------------------------------------------------
9 |
10 | // Target uC: TM4C123GH6PM
11 | // System Clock: 40 MHz
12 |
13 | //-----------------------------------------------------------------------------
14 | // Device includes, defines, and assembler directives
15 | //-----------------------------------------------------------------------------
16 |
17 | #include
18 | #include
19 | #include "tm4c123gh6pm.h"
20 | #include "enc28j60.h"
21 | #include "wait.h"
22 |
23 | #include
24 |
25 |
26 | #pragma pack(1)
27 |
28 | // ------------------------------------------------------------------------------
29 | // Globals
30 | // ------------------------------------------------------------------------------
31 |
32 | uint8_t nextPacketLsb = 0x00;
33 | uint8_t nextPacketMsb = 0x00;
34 |
35 |
36 |
37 | //-----------------------------------------------------------------------------
38 | // Subroutines
39 | //-----------------------------------------------------------------------------
40 |
41 | void spiWrite(uint8_t data)
42 | {
43 | #if IOT_COURSE_TEST
44 |
45 | SSI0_DR_R = data;
46 | while (SSI0_SR_R & SSI_SR_BSY);
47 |
48 | #else
49 | SSI2_DR_R = data;
50 | while (SSI2_SR_R & SSI_SR_BSY);
51 | #endif
52 | }
53 |
54 | uint8_t spiRead()
55 | {
56 | #if IOT_COURSE_TEST
57 |
58 | return SSI0_DR_R;
59 |
60 | #else
61 | return SSI2_DR_R;
62 | #endif
63 | }
64 |
65 | void etherCsOn()
66 | {
67 | PIN_ETHER_CS = 0;
68 | __asm (" NOP"); // allow line to settle
69 | __asm (" NOP");
70 | __asm (" NOP");
71 | __asm (" NOP");
72 | }
73 |
74 | void etherCsOff()
75 | {
76 | PIN_ETHER_CS = 1;
77 | }
78 |
79 | void etherWriteReg(uint8_t reg, uint8_t data)
80 | {
81 | etherCsOn();
82 | spiWrite(0x40 | (reg & 0x1F));
83 | spiRead();
84 | spiWrite(data);
85 | spiRead();
86 | etherCsOff();
87 | }
88 |
89 | uint8_t etherReadReg(uint8_t reg)
90 | {
91 | uint8_t data;
92 | etherCsOn();
93 | spiWrite(0x00 | (reg & 0x1F));
94 | spiRead();
95 | spiWrite(0);
96 | data = spiRead();
97 | etherCsOff();
98 | return data;
99 | }
100 |
101 | void etherSetReg(uint8_t reg, uint8_t mask)
102 | {
103 | etherCsOn();
104 | spiWrite(0x80 | (reg & 0x1F));
105 | spiRead();
106 | spiWrite(mask);
107 | spiRead();
108 | etherCsOff();
109 | }
110 |
111 | void etherClearReg(uint8_t reg, uint8_t mask)
112 | {
113 | etherCsOn();
114 | spiWrite(0xA0 | (reg & 0x1F));
115 | spiRead();
116 | spiWrite(mask);
117 | spiRead();
118 | etherCsOff();
119 | }
120 |
121 | void etherSetBank(uint8_t reg)
122 | {
123 | etherClearReg(ECON1, 0x03);
124 | etherSetReg(ECON1, reg >> 5);
125 | }
126 |
127 | void etherWritePhy(uint8_t reg, uint16_t data)
128 | {
129 | etherSetBank(MIREGADR);
130 | etherWriteReg(MIREGADR, reg);
131 | etherWriteReg(MIWRL, data & 0xFF);
132 | etherWriteReg(MIWRH, (data >> 8) & 0xFF);
133 | }
134 |
135 | uint16_t etherReadPhy(uint8_t reg)
136 | {
137 | uint16_t data, data2;
138 | etherSetBank(MIREGADR);
139 | etherWriteReg(MIREGADR, reg);
140 | etherWriteReg(MICMD, etherReadReg(MICMD) | MIIRD);
141 | waitMicrosecond(50);
142 | while ((etherReadReg(MISTAT) | MIBUSY) != 0);
143 | etherWriteReg(MICMD, etherReadReg(MICMD) & ~MIIRD);
144 | data = etherReadReg(MIRDL);
145 | data2 = etherReadReg(MIRDH);
146 | data |= (data2 << 8);
147 | return data;
148 | }
149 |
150 | void etherWriteMemStart()
151 | {
152 | etherCsOn();
153 | spiWrite(0x7A);
154 | spiRead();
155 | }
156 |
157 | void etherWriteMem(uint8_t data)
158 | {
159 | spiWrite(data);
160 | spiRead();
161 | }
162 |
163 | void etherWriteMemStop()
164 | {
165 | etherCsOff();
166 | }
167 |
168 | void etherReadMemStart()
169 | {
170 | etherCsOn();
171 | spiWrite(0x3A);
172 | spiRead();
173 | }
174 |
175 | uint8_t etherReadMem()
176 | {
177 | spiWrite(0);
178 | return spiRead();
179 | }
180 |
181 | void etherReadMemStop()
182 | {
183 | etherCsOff();
184 | }
185 |
186 |
187 | void setPhyMacAddr(uint8_t *macAddr)
188 | {
189 | // setup mac address
190 | etherSetBank(MAADR0);
191 | etherWriteReg(MAADR5, macAddr[0]);
192 | etherWriteReg(MAADR4, macAddr[1]);
193 | etherWriteReg(MAADR3, macAddr[2]);
194 | etherWriteReg(MAADR2, macAddr[3]);
195 | etherWriteReg(MAADR1, macAddr[4]);
196 | etherWriteReg(MAADR0, macAddr[5]);
197 |
198 | }
199 |
200 |
201 | // Initializes ethernet device
202 | // Uses order suggested in Chapter 6 of datasheet except 6.4 OST which is first here
203 | void etherInit(uint8_t mode, uint8_t *macAddress)
204 | {
205 | // make sure that oscillator start-up timer has expired
206 | while ((etherReadReg(ESTAT) & CLKRDY) == 0) {}
207 |
208 | // disable transmission and reception of packets
209 | etherClearReg(ECON1, RXEN);
210 | etherClearReg(ECON1, TXRTS);
211 |
212 | // initialize receive buffer space
213 | etherSetBank(ERXSTL);
214 | etherWriteReg(ERXSTL, LOBYTE(0x0000));
215 | etherWriteReg(ERXSTH, HIBYTE(0x0000));
216 | etherWriteReg(ERXNDL, LOBYTE(0x1A09));
217 | etherWriteReg(ERXNDH, HIBYTE(0x1A09));
218 |
219 | // initialize receiver write and read ptrs
220 | // at startup, will write from 0 to 1A08 only and will not overwrite rd ptr
221 | etherWriteReg(ERXWRPTL, LOBYTE(0x0000));
222 | etherWriteReg(ERXWRPTH, HIBYTE(0x0000));
223 | etherWriteReg(ERXRDPTL, LOBYTE(0x1A09));
224 | etherWriteReg(ERXRDPTH, HIBYTE(0x1A09));
225 | etherWriteReg(ERDPTL, LOBYTE(0x0000));
226 | etherWriteReg(ERDPTH, HIBYTE(0x0000));
227 |
228 | // setup receive filter
229 | // always check CRC, use OR mode
230 | etherSetBank(ERXFCON);
231 | etherWriteReg(ERXFCON, (mode | 0x20) & 0xBF);
232 | // bring mac out of reset
233 | etherSetBank(MACON2);
234 | etherWriteReg(MACON2, 0);
235 |
236 | // enable mac rx, enable pause control for full duplex
237 | etherWriteReg(MACON1, TXPAUS | RXPAUS | MARXEN);
238 |
239 | // enable padding to 60 bytes (no runt packets)
240 | // add crc to tx packets, set full or half duplex
241 | if ((mode & ETHER_FULLDUPLEX) != 0)
242 | etherWriteReg(MACON3, FULDPX | FRMLNEN | TXCRCEN | PAD60);
243 | else
244 | etherWriteReg(MACON3, FRMLNEN | TXCRCEN | PAD60);
245 |
246 | // leave MACON4 as reset
247 |
248 | // set maximum rx packet size
249 | etherWriteReg(MAMXFLL, LOBYTE(1518));
250 | etherWriteReg(MAMXFLH, HIBYTE(1518));
251 |
252 | // set back-to-back uint8_ter-packet gap to 9.6us
253 | if ((mode & ETHER_FULLDUPLEX) != 0)
254 | etherWriteReg(MABBIPG, 0x15);
255 | else
256 | etherWriteReg(MABBIPG, 0x12);
257 |
258 | // set non-back-to-back uint8_ter-packet gap registers
259 | etherWriteReg(MAIPGL, 0x12);
260 | etherWriteReg(MAIPGH, 0x0C);
261 |
262 | // leave collision window MACLCON2 as reset
263 |
264 | setPhyMacAddr(macAddress);
265 |
266 | // initialize phy duplex
267 | if ((mode & ETHER_FULLDUPLEX) != 0)
268 | etherWritePhy(PHCON1, PDPXMD);
269 | else
270 | etherWritePhy(PHCON1, 0);
271 |
272 | // disable phy loopback if in half-duplex mode
273 | etherWritePhy(PHCON2, HDLDIS);
274 |
275 | // set LEDA (link status) and LEDB (tx/rx activity)
276 | // stretch LED on to 40ms (default)
277 | etherWritePhy(PHLCON, 0x0472);
278 |
279 | // enable reception
280 | etherSetReg(ECON1, RXEN);
281 | }
282 |
283 | // Returns TRUE if packet received
284 | uint8_t etherKbhit()
285 | {
286 | return ((etherReadReg(EIR) & PKTIF) != 0);
287 | }
288 |
289 | // Returns up to max_size characters in data buffer
290 | // Returns number of bytes copied to buffer
291 | // Contents written are 16-bit size, 16-bit status, payload excl crc
292 | uint16_t etherGetPacket(uint8_t data[], uint16_t max_size)
293 | {
294 | uint16_t i = 0, size, tmp;
295 |
296 | // enable read from FIFO buffers
297 | etherReadMemStart();
298 |
299 | // get next pckt information
300 | nextPacketLsb = etherReadMem();
301 | nextPacketMsb = etherReadMem();
302 |
303 | // calc size
304 | // don't return crc, instead return size + status, so size is correct
305 | size = etherReadMem();
306 | data[i++] = size;
307 | tmp = etherReadMem();
308 | data[i++] = tmp;
309 | size |= (tmp << 8);
310 |
311 | // copy status + data
312 | if (size > max_size)
313 | size = max_size;
314 | while (i < size)
315 | data[i++] = etherReadMem();
316 |
317 | // end read from FIFO buffers
318 | etherReadMemStop();
319 |
320 | // advance read ptr
321 | etherSetBank(ERXRDPTL);
322 | etherWriteReg(ERXRDPTL, nextPacketLsb); // hw ptr
323 | etherWriteReg(ERXRDPTH, nextPacketMsb);
324 | etherWriteReg(ERDPTL, nextPacketLsb); // dma rd ptr
325 | etherWriteReg(ERDPTH, nextPacketMsb);
326 |
327 | // decrement packet counter so that PKTIF is maintained correctly
328 | etherSetReg(ECON2, PKTDEC);
329 |
330 | return size;
331 | }
332 |
333 | // Returns TRUE is rx buffer overflowed after correcting the problem
334 | uint8_t etherIsOverflow()
335 | {
336 | uint8_t err;
337 | err = (etherReadReg(EIR) & RXERIF) != 0;
338 | if (err)
339 | etherClearReg(EIR, RXERIF);
340 | return err;
341 | }
342 |
343 | // Writes a packet
344 | int16_t etherPutPacket(uint8_t data[], uint16_t size)
345 | {
346 | uint16_t i;
347 |
348 | // clear out any tx errors
349 | if ((etherReadReg(EIR) & TXERIF) != 0)
350 | {
351 | etherClearReg(EIR, TXERIF);
352 | etherSetReg(ECON1, TXRTS);
353 | etherClearReg(ECON1, TXRTS);
354 | }
355 |
356 | // set DMA start address
357 | etherSetBank(EWRPTL);
358 | etherWriteReg(EWRPTL, LOBYTE(0x1A0A));
359 | etherWriteReg(EWRPTH, HIBYTE(0x1A0A));
360 |
361 | // start FIFO buffer write
362 | etherWriteMemStart();
363 |
364 | // write control byte
365 | etherWriteMem(0);
366 |
367 | // write data
368 | for (i = 0; i < size; i++)
369 | etherWriteMem(data[i]);
370 |
371 | // stop write
372 | etherWriteMemStop();
373 |
374 | // request transmit
375 | etherWriteReg(ETXSTL, LOBYTE(0x1A0A));
376 | etherWriteReg(ETXSTH, HIBYTE(0x1A0A));
377 | etherWriteReg(ETXNDL, LOBYTE(0x1A0A+size));
378 | etherWriteReg(ETXNDH, HIBYTE(0x1A0A+size));
379 | etherClearReg(EIR, TXIF);
380 | etherSetReg(ECON1, TXRTS);
381 |
382 | // wait for completion
383 | while ((etherReadReg(ECON1) & TXRTS) != 0);
384 |
385 | // determine success
386 | return ((etherReadReg(ESTAT) & TXABORT) == 0);
387 | }
388 |
389 |
390 |
391 |
392 |
--------------------------------------------------------------------------------
/enc28j60.h:
--------------------------------------------------------------------------------
1 | // ENC28J60 Driver
2 | // Jason Losh
3 |
4 | //-----------------------------------------------------------------------------
5 | // Hardware Target
6 | //-----------------------------------------------------------------------------
7 |
8 | // Target uC: TM4C123GH6PM
9 | // System Clock: 40 MHz
10 |
11 | #ifndef ENC28J60_H_
12 | #define ENC28J60_H_
13 |
14 |
15 | #include "ethernet.h"
16 | #include "network_utilities.h"
17 | #include "ipv4.h"
18 |
19 | #define IOT_COURSE_TEST 0
20 |
21 |
22 | //-----------------------------------------------------------------------------
23 | // Subroutines
24 | //-----------------------------------------------------------------------------
25 |
26 | // Buffer is configured as follows
27 | // Receive buffer starts at 0x0000 (bottom 6666 bytes of 8K space)
28 | // Transmit buffer at 01A0A (top 1526 bytes of 8K space)
29 |
30 | // ------------------------------------------------------------------------------
31 | // Defines
32 | // ------------------------------------------------------------------------------
33 |
34 | // Pins
35 | #if IOT_COURSE_TEST
36 |
37 | #define PIN_ETHER_CS (*((volatile uint32_t *)(0x42000000 + (0x400043FC-0x40000000)*32 + 3*4)))
38 |
39 | //#define PIN_ETHER_CS (*((volatile uint32_t *)(0x42000000 + (0x400073FC-0x40000000)*32 + 1*4)))
40 |
41 |
42 | #else
43 | #define PIN_ETHER_CS (*((volatile uint32_t *)(0x42000000 + (0x400053FC-0x40000000)*32 + 5*4)))
44 |
45 | #endif
46 |
47 | #define ETHER_UNICAST 0x80
48 | #define ETHER_BROADCAST 0x01
49 | #define ETHER_MULTICAST 0x02
50 | #define ETHER_HASHTABLE 0x04
51 | #define ETHER_MAGICPACKET 0x08
52 | #define ETHER_PATTERNMATCH 0x10
53 |
54 | #define ETHER_HALFDUPLEX 0x00
55 | #define ETHER_FULLDUPLEX 0x40
56 |
57 | // Ether registers
58 | #define ERDPTL 0x00
59 | #define ERDPTH 0x01
60 | #define EWRPTL 0x02
61 | #define EWRPTH 0x03
62 | #define ETXSTL 0x04
63 | #define ETXSTH 0x05
64 | #define ETXNDL 0x06
65 | #define ETXNDH 0x07
66 | #define ERXSTL 0x08
67 | #define ERXSTH 0x09
68 | #define ERXNDL 0x0A
69 | #define ERXNDH 0x0B
70 | #define ERXRDPTL 0x0C
71 | #define ERXRDPTH 0x0D
72 | #define ERXWRPTL 0x0E
73 | #define ERXWRPTH 0x0F
74 | #define EIE 0x1B
75 | #define EIR 0x1C
76 | #define RXERIF 0x01
77 | #define TXERIF 0x02
78 | #define TXIF 0x08
79 | #define PKTIF 0x40
80 | #define ESTAT 0x1D
81 | #define CLKRDY 0x01
82 | #define TXABORT 0x02
83 | #define ECON2 0x1E
84 | #define PKTDEC 0x40
85 | #define ECON1 0x1F
86 | #define RXEN 0x04
87 | #define TXRTS 0x08
88 | #define ERXFCON 0x38
89 | #define EPKTCNT 0x39
90 | #define MACON1 0x40
91 | #define MARXEN 0x01
92 | #define RXPAUS 0x04
93 | #define TXPAUS 0x08
94 | #define MACON2 0x41
95 | #define MARST 0x80
96 | #define MACON3 0x42
97 | #define FULDPX 0x01
98 | #define FRMLNEN 0x02
99 | #define TXCRCEN 0x10
100 | #define PAD60 0x20
101 | #define MACON4 0x43
102 | #define MABBIPG 0x44
103 | #define MAIPGL 0x46
104 | #define MAIPGH 0x47
105 | #define MACLCON1 0x48
106 | #define MACLCON2 0x49
107 | #define MAMXFLL 0x4A
108 | #define MAMXFLH 0x4B
109 | #define MICMD 0x52
110 | #define MIIRD 0x01
111 | #define MIREGADR 0x54
112 | #define MIWRL 0x56
113 | #define MIWRH 0x57
114 | #define MIRDL 0x58
115 | #define MIRDH 0x59
116 | #define MAADR1 0x60
117 | #define MAADR0 0x61
118 | #define MAADR3 0x62
119 | #define MAADR2 0x63
120 | #define MAADR5 0x64
121 | #define MAADR4 0x65
122 | #define MISTAT 0x6A
123 | #define MIBUSY 0x01
124 | #define ECOCON 0x75
125 |
126 | // Ether phy registers
127 | #define PHCON1 0x00
128 | #define PDPXMD 0x0100
129 | #define PHCON2 0x10
130 | #define HDLDIS 0x0100
131 | #define PHLCON 0x14
132 |
133 | // ------------------------------------------------------------------------------
134 | // Macros
135 | // ------------------------------------------------------------------------------
136 |
137 | #define LOBYTE(x) ((x) & 0xFF)
138 | #define HIBYTE(x) (((x) >> 8) & 0xFF)
139 |
140 |
141 |
142 |
143 | typedef struct enc28j60Frame // 4-bytes
144 | {
145 | uint16_t size;
146 | uint16_t status;
147 | uint8_t data;
148 |
149 | }enc28j60_frame_t;
150 |
151 | enc28j60_frame_t *enc28j60;
152 |
153 |
154 |
155 |
156 | // ------------------------------------------------------------------------------
157 | // Functions
158 | // ------------------------------------------------------------------------------
159 |
160 | void etherInit(uint8_t mode, uint8_t *macAddress);
161 |
162 | void setPhyMacAddr(uint8_t *macAddr);
163 |
164 | void etherWritePhy(uint8_t reg, uint16_t data);
165 | uint16_t etherReadPhy(uint8_t reg);
166 | uint8_t etherKbhit();
167 | uint16_t etherGetPacket(uint8_t data[], uint16_t max_size);
168 | uint8_t etherIsOverflow();
169 | int16_t etherPutPacket(uint8_t data[], uint16_t size);
170 |
171 |
172 |
173 |
174 | #endif
175 |
--------------------------------------------------------------------------------
/main.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file main.c
4 | * @author Aditya Mall,
5 | * @brief Network API test app file
6 | *
7 | * Info
8 | * Target Platform : EK-TM4C123GXL w/ ENC28J60
9 | * Target uC : TM4C123GH6PM
10 | * System Clock : 40 MHz
11 | *
12 | * Hardware configuration :-
13 | * ENC28J60 Ethernet controller
14 | * MOSI (SSI2Tx) on PB7
15 | * MISO (SSI2Rx) on PB6
16 | * SCLK (SSI2Clk) on PB4
17 | * ~CS connected to PB1
18 | *
19 | ******************************************************************************
20 | * @attention
21 | *
22 | * © COPYRIGHT(c) 2019 Aditya Mall, MIT License
23 | *
24 | * Copyright (c) 2019 Aditya Mall
25 | *
26 | * Please Take prior permission from Dr. Jason Losh and Respective Owners of the,
27 | * API Libraries if you are a student at The University of Texas at Arlington and,
28 | * wish to use part of the code in your project.
29 | *
30 | * The above copyright notice and this permission notice shall be included in all
31 | * copies or substantial portions of the Software.
32 | *
33 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
34 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
37 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
40 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
42 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 | *
44 | ******************************************************************************
45 | */
46 |
47 |
48 | /*
49 | ******************************************************************************
50 | *
51 | * Repository Information :-
52 | *
53 | * Clone "clterm" Repo from : https://github.com/adimalla/clTerm
54 | * Clone "MQTT-3.1-C" Repo from : https://github.com/adimalla/MQTT-3.1-C
55 | *
56 | ******************************************************************************
57 | */
58 |
59 |
60 | /*
61 | * Standard header and API header files
62 | */
63 | #include
64 | #include
65 | #include
66 | #include
67 | #include "tm4c123gh6pm.h"
68 | #include "enc28j60.h"
69 | #include "wait.h"
70 |
71 | #include "ethernet.h"
72 | #include "network_utilities.h"
73 | #include "arp.h"
74 | #include "ipv4.h"
75 | #include "icmp.h"
76 | #include "udp.h"
77 | #include "dhcp.h"
78 | #include "tcp.h"
79 |
80 | #include "cl_term.h"
81 | #include "mqtt_client.h"
82 |
83 |
84 |
85 | /******************************************************************************/
86 | /* */
87 | /* Data Structures and Defines */
88 | /* */
89 | /******************************************************************************/
90 |
91 |
92 | #define STATIC 1
93 | #define ICMP_TEST 1
94 | #define UDP_TEST 0
95 | #define TCP_TEST 0
96 | #define MQTT_TEST 1
97 |
98 |
99 | #define RED_LED (*((volatile uint32_t *)(0x42000000 + (0x400253FC-0x40000000)*32 + 1*4)))
100 | #define GREEN_LED (*((volatile uint32_t *)(0x42000000 + (0x400253FC-0x40000000)*32 + 3*4)))
101 | #define BLUE_LED (*((volatile uint32_t *)(0x42000000 + (0x400253FC-0x40000000)*32 + 2*4)))
102 | #define PUSH_BUTTON (*((volatile uint32_t *)(0x42000000 + (0x400253FC-0x40000000)*32 + 4*4)))
103 |
104 |
105 |
106 | typedef enum _app_state
107 | {
108 | APP_INIT = 0,
109 | APP_READ = 1,
110 | APP_WRITE = 2,
111 | USER_INPUT = 3,
112 |
113 | }app_state_t;
114 |
115 |
116 |
117 | /******************************************************************************/
118 | /* */
119 | /* Functions Implementations */
120 | /* */
121 | /******************************************************************************/
122 |
123 |
124 | void initHw()
125 | {
126 | // Configure HW to work with 16 MHz XTAL, PLL enabled, system clock of 40 MHz
127 | SYSCTL_RCC_R = SYSCTL_RCC_XTAL_16MHZ | SYSCTL_RCC_OSCSRC_MAIN | SYSCTL_RCC_USESYSDIV | (4 << SYSCTL_RCC_SYSDIV_S);
128 |
129 | // Set GPIO ports to use APB (not needed since default configuration -- for clarity)
130 | // Note UART on port A must use APB
131 | SYSCTL_GPIOHBCTL_R = 0;
132 |
133 | // Enable GPIO port B and E peripherals
134 | SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOB | SYSCTL_RCGC2_GPIOD | SYSCTL_RCGC2_GPIOF | SYSCTL_RCGC2_GPIOA | SYSCTL_RCGC2_GPIOE;
135 |
136 | // Configure LED and pushbutton pins
137 | GPIO_PORTF_DIR_R = 0x0E; // bits 1-3 are outputs, other pins are inputs
138 | GPIO_PORTF_DR2R_R = 0x0E; // set drive strength to 2mA (not needed since default configuration -- for clarity)
139 | GPIO_PORTF_DEN_R = 0x1E; // enable LEDs and pushbuttons
140 | GPIO_PORTF_PUR_R = 0x1E; // enable internal pull-up for push button
141 |
142 | #if IOT_COURSE_TEST /* IOT Networking Student Hardware check */
143 |
144 | // Configure ~CS for ENC28J60
145 | GPIO_PORTA_DIR_R = (1 << 3); // make bit 1 an output
146 | GPIO_PORTA_DEN_R = (1 << 3); // enable bits 1 for digital
147 |
148 | // GPIO_PORTD_DIR_R = (1 << 1); // make bit 1 an output
149 | // GPIO_PORTD_DEN_R = (1 << 1); // enable bits 1 for digital
150 |
151 | SYSCTL_RCGCSSI_R |= SYSCTL_RCGCSSI_R0;
152 | GPIO_PORTA_DIR_R |= ( 1 << 2) | (1 << 3) | (1 << 5);
153 | GPIO_PORTA_DR2R_R |= ( 1 << 2) | (1 << 4) | (1 << 5);
154 | GPIO_PORTA_AFSEL_R |= ( 1 << 2) | (1 << 4) | (1 << 5);
155 | GPIO_PORTA_PCTL_R = GPIO_PCTL_PA5_SSI0TX | GPIO_PCTL_PA4_SSI0RX | GPIO_PCTL_PA2_SSI0CLK;
156 | GPIO_PORTA_DEN_R |= ( 1<< 2) | (1 << 4) | (1 << 5);
157 |
158 | SSI0_CR1_R &= ~SSI_CR1_SSE;
159 | SSI0_CR1_R = 0; // select master mode
160 | SSI0_CC_R = 0; // select system clock as the clock source
161 | SSI0_CPSR_R = 20; // set bit rate to 1 MHz (if SR=0 in CR0)
162 | SSI0_CR0_R = SSI_CR0_FRF_MOTO | SSI_CR0_DSS_8; // set SR=0, mode 0 (SPH=0, SPO=0), 8-bit
163 | SSI0_CR1_R |= SSI_CR1_SSE;
164 |
165 | #else
166 |
167 | // Configure ~CS for ENC28J60
168 | GPIO_PORTB_DIR_R = (1 << 5); // make bit 1 an output
169 | GPIO_PORTB_DEN_R = (1 << 5); // enable bits 1 for digital
170 |
171 | // Configure SSI2 pins for SPI configuration
172 | SYSCTL_RCGCSSI_R |= SYSCTL_RCGCSSI_R2; // turn-on SSI2 clocking
173 | GPIO_PORTB_DIR_R |= 0x90; // make bits 4 and 7 outputs
174 | GPIO_PORTB_DR2R_R |= 0x90; // set drive strength to 2mA
175 | GPIO_PORTB_AFSEL_R |= 0xD0; // select alternative functions for MOSI, MISO, SCLK pins
176 | GPIO_PORTB_PCTL_R = GPIO_PCTL_PB7_SSI2TX | \
177 | GPIO_PCTL_PB6_SSI2RX | \
178 | GPIO_PCTL_PB4_SSI2CLK; // map alt fns to SSI2
179 | GPIO_PORTB_DEN_R |= 0xD0; // enable digital operation on TX, RX, CLK pins
180 |
181 | // Configure the SSI2 as a SPI master, mode 3, 8bit operation, 1 MHz bit rate
182 | SSI2_CR1_R &= ~SSI_CR1_SSE; // turn off SSI2 to allow re-configuration
183 | SSI2_CR1_R = 0; // select master mode
184 | SSI2_CC_R = 0; // select system clock as the clock source
185 | SSI2_CPSR_R = 40; // set bit rate to 1 MHz (if SR=0 in CR0)
186 | SSI2_CR0_R = SSI_CR0_FRF_MOTO | SSI_CR0_DSS_8; // set SR=0, mode 0 (SPH=0, SPO=0), 8-bit
187 | SSI2_CR1_R |= SSI_CR1_SSE; // turn on SSI2
188 |
189 | #endif
190 |
191 | }
192 |
193 |
194 | void init_uart0(void)
195 | {
196 | // Enable GPIO port F peripherals
197 | SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOA;
198 |
199 | // Configure UART0 pins
200 | SYSCTL_RCGCUART_R |= SYSCTL_RCGCUART_R0; // Turn-on UART0, leave other uarts in same status
201 | GPIO_PORTA_DEN_R |= 3; // Turn on Digital Operations on PA0 and PA1
202 | GPIO_PORTA_AFSEL_R |= 3; // Select Alternate Functionality on PA0 and PA1
203 | GPIO_PORTA_PCTL_R |= GPIO_PCTL_PA1_U0TX | GPIO_PCTL_PA0_U0RX; // Select UART0 Module
204 |
205 | // Configure UART0 to 115200 baud, 8N1 format (must be 3 clocks from clock enable and config writes)
206 | UART0_CTL_R = 0; // turn-off UART0 to allow safe programming
207 | UART0_CC_R |= UART_CC_CS_SYSCLK; // use system clock (40 MHz)
208 | UART0_IBRD_R = 21; // r = 40 MHz / (Nx115.2kHz), set floor(r)=21, where N=16
209 | UART0_FBRD_R = 45; // round(fract(r)*64)=45
210 | UART0_LCRH_R |= UART_LCRH_WLEN_8 | UART_LCRH_FEN; // configure for 8N1 w/ 16-level FIFO
211 | UART0_CTL_R |= UART_CTL_TXE | UART_CTL_RXE | UART_CTL_UARTEN; // enable TX, RX, and module
212 |
213 | }
214 |
215 |
216 | // Blocking function that writes a serial character when the UART buffer is not full
217 | void putcUart0(const char c)
218 | {
219 | while(UART0_FR_R & UART_FR_TXFF);
220 | UART0_DR_R = c;
221 |
222 | }
223 |
224 |
225 | // Blocking function that returns with serial data once the buffer is not empty
226 | char getcUart0(void)
227 | {
228 | while (UART0_FR_R & UART_FR_RXFE);
229 | return UART0_DR_R & 0xFF;
230 | }
231 |
232 |
233 |
234 | // Blocking function that writes a string when the UART buffer is not full
235 | void putsUart0(const char* str)
236 | {
237 | uint8_t i;
238 |
239 | for (i = 0; i < strlen(str); i++)
240 | putcUart0(str[i]);
241 | }
242 |
243 |
244 |
245 | void init_adc(void)
246 | {
247 |
248 | // Enable GPIO port B and E peripherals
249 |
250 | // Configure AN0 as an analog input
251 | SYSCTL_RCGCADC_R |= SYSCTL_RCGCADC_R0; // turn on ADC module 0 clocking
252 | GPIO_PORTE_AFSEL_R |= (1 << 3); // select alternative functions for AN0 (PE3)
253 | GPIO_PORTE_DEN_R &= ~(1 << 3); // turn off digital operation on pin PE3
254 | GPIO_PORTE_AMSEL_R |= (1 << 3); // turn on analog operation on pin PE3
255 | ADC0_CC_R = ADC_CC_CS_SYSPLL; // select PLL as the time base (not needed, since default value)
256 | ADC0_ACTSS_R &= ~ADC_ACTSS_ASEN3; // disable sample sequencer 3 (SS3) for programming
257 | ADC0_EMUX_R = ADC_EMUX_EM3_PROCESSOR; // select SS3 bit in ADCPSSI as trigger
258 | ADC0_SSMUX3_R = 0; // set first sample to AN0
259 | ADC0_SSCTL3_R = ADC_SSCTL3_END0 | ADC_SSCTL3_TS0; // mark first sample as the end
260 | ADC0_ACTSS_R |= ADC_ACTSS_ASEN3; // enable SS3 for operation
261 |
262 | }
263 |
264 |
265 | uint16_t readAdc0Ss3()
266 | {
267 | ADC0_PSSI_R |= ADC_PSSI_SS3; // set start bit
268 | while (ADC0_ACTSS_R & ADC_ACTSS_BUSY); // wait until SS3 is not busy
269 | return ADC0_SSFIFO3_R & 0x0F; // get single result from the FIFO
270 | }
271 |
272 |
273 |
274 | /* wrapper Functions */
275 |
276 | uint8_t ether_open(uint8_t *mac_address)
277 | {
278 |
279 | etherInit(ETHER_UNICAST | ETHER_BROADCAST | ETHER_HALFDUPLEX, mac_address);
280 |
281 | return 0;
282 | }
283 |
284 |
285 | uint8_t myUartOpen(uint32_t baud_rate)
286 | {
287 | init_uart0();
288 |
289 | //return 1 for success, here
290 | return 1;
291 | }
292 |
293 |
294 | uint8_t myPutChar(char data)
295 | {
296 | putcUart0(data);
297 |
298 | return 0;
299 | }
300 |
301 |
302 |
303 | /* Link Console operation functions */
304 | console_ops_t myUartOperations =
305 | {
306 |
307 | .open = myUartOpen,
308 | .print_char = myPutChar,
309 | .read_char = getcUart0,
310 |
311 | };
312 |
313 |
314 | /* Link Network operation functions */
315 | ether_operations_t ether_ops =
316 | {
317 | .open = ether_open,
318 | .network_interface_status = etherKbhit,
319 | .ether_send_packet = etherPutPacket,
320 | .ether_recv_packet = etherGetPacket,
321 | .random_gen_seed = readAdc0Ss3,
322 | };
323 |
324 |
325 |
326 | /* Main */
327 | int main(void)
328 | {
329 |
330 | enc28j60_frame_t *network_hardware;
331 | ethernet_handle_t *ethernet;
332 |
333 | uint8_t loop = 0;
334 | int16_t retval = 0;
335 |
336 | /* Network Data Buffer */
337 | uint8_t data[ETHER_MTU_SIZE] = {0};
338 |
339 | cl_term_t *my_console;
340 | char serial_buffer[MAX_INPUT_SIZE] = {0};
341 |
342 | /* Point Network data */
343 | network_hardware = (void*)data;
344 |
345 | /* init controller */
346 | initHw();
347 |
348 | init_adc();
349 |
350 | /* Console Configurations */
351 | my_console = console_open(&myUartOperations, 115200, serial_buffer, CONSOLE_STATIC);
352 |
353 | console_print(my_console, CONSOLE_CLEAR_SCREEN);
354 |
355 | /* Create Ethernet handle */
356 | ethernet = create_ethernet_handle(&network_hardware->data, "02:03:04:50:60:48", "192.168.1.199", ðer_ops);
357 |
358 | /* flash PHY LEDS */
359 | etherWritePhy(PHLCON, 0x0880);
360 | RED_LED = 1;
361 | waitMicrosecond(500000);
362 | etherWritePhy(PHLCON, 0x0990);
363 | RED_LED = 0;
364 | waitMicrosecond(500000);
365 |
366 |
367 | #if STATIC
368 |
369 | set_ip_address(ethernet->gateway_ip, "192.168.1.196");
370 |
371 | #else
372 |
373 | /* test DHCP */
374 | ether_get_dhcp_ip(ethernet, (uint8_t*)network_hardware, ethernet->host_mac, DHCP_INIT_STATE);
375 |
376 | #endif
377 |
378 |
379 | #if ICMP_TEST
380 |
381 | /* Test ICM, ARP packets */
382 | uint8_t sequence_no = 1;
383 |
384 | ether_send_arp_req(ethernet, ethernet->host_ip, ethernet->gateway_ip);
385 |
386 | if(ether_is_arp(ethernet, (uint8_t*)network_hardware, 128))
387 | {
388 |
389 | ether_handle_arp_resp_req(ethernet);
390 |
391 | GREEN_LED = 1;
392 | waitMicrosecond(50000);
393 | GREEN_LED = 0;
394 | }
395 |
396 |
397 | /* Test ICMP packets */
398 | ether_send_icmp_req(ethernet, ICMP_ECHOREQUEST, ethernet->gateway_ip, &sequence_no, \
399 | ethernet->arp_table[0].mac_address, ethernet->host_mac);
400 | #endif
401 |
402 |
403 | #if UDP_TEST
404 |
405 | ether_send_udp(ethernet, ethernet->gateway_ip, 8080, "Hello", 5);
406 |
407 | ether_read_udp(ethernet, (uint8_t*)network_hardware, udp_data, APP_BUFF_SIZE);
408 |
409 | if(strncmp(udp_data, "Hello from server", 18) == 0)
410 | ether_send_udp(ethernet, ethernet->gateway_ip, 8080, "Hello again", 11);
411 |
412 | #endif
413 |
414 |
415 | #if TCP_TEST
416 | /* Test TCP application */
417 | uint16_t tcp_src_port = 0;
418 | uint16_t tcp_dest_port = 0;
419 | int32_t tcp_retval = 0;
420 | int16_t input_length = 0;
421 |
422 | uint16_t count = 0;
423 |
424 |
425 | char tcp_data[50] = {0};
426 | uint8_t destination_ip[4] = {0};
427 |
428 | set_ip_address(destination_ip, "192.168.1.13");
429 |
430 | tcp_handle_t *test_client;
431 |
432 | /* APP state machine */
433 | app_state_t app_state = APP_INIT;
434 |
435 | loop = 1 ;
436 |
437 |
438 | while(loop)
439 | {
440 | switch(app_state)
441 | {
442 |
443 | case APP_INIT:
444 |
445 | tcp_dest_port = 7788;
446 |
447 | tcp_src_port = get_random_port(ethernet, 6534);
448 |
449 | test_client = ether_tcp_create_client(ethernet, (uint8_t*)network_hardware, tcp_src_port, tcp_dest_port, destination_ip);
450 |
451 | ether_tcp_connect(ethernet, (uint8_t*)network_hardware, test_client);
452 |
453 | tcp_control(test_client, TCP_READ_NONBLOCK);
454 |
455 | app_state = APP_WRITE;
456 |
457 | break;
458 |
459 |
460 | case APP_READ:
461 |
462 | tcp_retval = 0;
463 |
464 | console_print(my_console, "Read State \n");
465 |
466 | ether_tcp_read_data(ethernet, (uint8_t*)network_hardware, test_client, tcp_data, 50);
467 |
468 | app_state = APP_WRITE;
469 |
470 | console_print(my_console,tcp_data);
471 | console_print(my_console, "\n");
472 |
473 | if(count > 100)
474 | {
475 | console_print(my_console,"Connection Closed");
476 |
477 | ether_tcp_close(ethernet, (uint8_t*)network_hardware, test_client);
478 | loop = 0;
479 | count = 0;
480 | }
481 |
482 | if(test_client->client_flags.connect_established == 0)
483 | {
484 | loop = 0;
485 | }
486 |
487 | break;
488 |
489 |
490 | case APP_WRITE:
491 |
492 | console_print(my_console, "Write State \n");
493 | #if 1
494 | input_length = 0;
495 |
496 | input_length = console_get_string(my_console, MAX_INPUT_SIZE);
497 |
498 | if(input_length)
499 | {
500 | tcp_retval = ether_tcp_send_data(ethernet, (uint8_t*)network_hardware, test_client, serial_buffer, input_length);
501 | }
502 | #else
503 |
504 | tcp_retval = ether_tcp_send_data(ethernet, (uint8_t*)network_hardware, test_client, "hey", 3);
505 |
506 | #endif
507 |
508 | if(tcp_retval > 0)
509 | count++;
510 |
511 | app_state = APP_READ;
512 |
513 | break;
514 |
515 | }
516 |
517 | }
518 | #endif
519 |
520 |
521 | #if MQTT_TEST
522 |
523 | /* Test MQTT application */
524 | uint16_t tcp_src_port = 0;
525 | uint16_t tcp_dest_port = 0;
526 | int16_t input_length = 0;
527 | uint8_t destination_ip[4] = {0};
528 |
529 | tcp_handle_t *test_client;
530 | mqtt_client_t publisher;
531 |
532 | /* Network API related variable initializations */
533 | char message[200] = {0};
534 | char read_buffer[150] = {0};
535 |
536 | /* Client State machine related variable initializations */
537 | size_t message_length = 0;
538 | int8_t message_status = 0;
539 | uint8_t loop_state = 0;
540 | uint8_t mqtt_message_state = 0;
541 |
542 | /* MQTT message buffers */
543 | char *my_client_name = "Sender|1990-adityamall";
544 | char user_name[] = "device1.sensor";
545 | char pass_word[] = "4321";
546 | char publish_topic[] = "device1/temp";
547 | char publish_message[20] = "hello ";
548 | char copy_publish_message[20] = {0};
549 |
550 | uint32_t count = 0;
551 | char count_buff[4] = {0};
552 |
553 | /* Configure/Connect to MQTT broker */
554 | set_ip_address(destination_ip, "192.168.1.196");
555 |
556 | tcp_dest_port = 1883;
557 | tcp_src_port = get_random_port(ethernet, 6534);
558 |
559 | /* Create TCP object/socket */
560 | test_client = ether_tcp_create_client(ethernet, (uint8_t*)network_hardware, tcp_src_port, tcp_dest_port, destination_ip);
561 |
562 | /*Connect to MQTT broker */
563 | ether_tcp_connect(ethernet, (uint8_t*)network_hardware, test_client);
564 |
565 | /* Configure TCP Network IO control */
566 | tcp_control(test_client, TCP_READ_NONBLOCK);
567 |
568 |
569 | /* MQTT State machine initializations */
570 | loop_state = FSM_RUN;
571 |
572 | /* Update state to connect to send connect message */
573 | mqtt_message_state = mqtt_connect_state;
574 |
575 | while(loop_state)
576 | {
577 | switch(mqtt_message_state)
578 | {
579 |
580 | case mqtt_idle_state:
581 |
582 |
583 | break;
584 |
585 | case mqtt_read_state:
586 |
587 | console_print(my_console, "READ \n");
588 |
589 | memset(read_buffer, 0, sizeof(read_buffer));
590 |
591 | while(ether_tcp_read_data(ethernet, (uint8_t*)network_hardware, test_client, read_buffer, 150) < 0);
592 |
593 | publisher.message = (void*)read_buffer;
594 |
595 | /* get MQTT message type and update state */
596 | mqtt_message_state = get_mqtt_message_type(&publisher);
597 | if(!mqtt_message_state)
598 | {
599 | mqtt_message_state = mqtt_disconnect_state;
600 | }
601 |
602 | break;
603 |
604 |
605 | case mqtt_connect_state:
606 |
607 | console_print(my_console, "CONNECT \n");
608 |
609 | /* Test connect message */
610 | memset(message, '\0', sizeof(message));
611 |
612 | publisher.connect_msg = (void*)message;
613 |
614 | /* Setup User name password (optional) */
615 | mqtt_client_username_passwd(&publisher, user_name, pass_word);
616 |
617 | /* Set connect options */
618 | mqtt_connect_options(&publisher, MQTT_CLEAN_SESSION, MQTT_MESSAGE_NO_RETAIN, MQTT_QOS_FIRE_FORGET);
619 |
620 | /* Setup MQTT CONNECT Message */
621 | message_length = mqtt_connect(&publisher, my_client_name, 6000);
622 |
623 | /* Send connect message */
624 | ether_tcp_send_data(ethernet, (uint8_t*)network_hardware, test_client, (char*)publisher.connect_msg, message_length);
625 |
626 | /* Update state */
627 | mqtt_message_state = mqtt_read_state;
628 |
629 | break;
630 |
631 |
632 | case mqtt_connack_state:
633 |
634 | console_print(my_console, "CONNACK \n");
635 |
636 | /* Check return code of CONNACK message */
637 | publisher.connack_msg = (void *)read_buffer;
638 |
639 | mqtt_message_state = get_connack_status(&publisher);
640 |
641 | if(!mqtt_message_state)
642 | mqtt_message_state = mqtt_publish_state;
643 |
644 | break;
645 |
646 |
647 | case mqtt_publish_state:
648 |
649 | console_print(my_console, "PUBLISH \n");
650 |
651 | /* Fill MQTT PUBLISH message structure */
652 | memset(message, '\0', sizeof(message));
653 |
654 | publisher.publish_msg = (void *)message;
655 |
656 | /*Configure publish options */
657 | mqtt_publish_options(&publisher, MQTT_MESSAGE_NO_RETAIN, MQTT_QOS_FIRE_FORGET);
658 |
659 | #if 0
660 | input_length = console_get_string(my_console, MAX_INPUT_SIZE);
661 |
662 | if(strcmp(serial_buffer,"exit") == 0 )
663 | {
664 | mqtt_message_state = mqtt_disconnect_state;
665 | break;
666 | }
667 |
668 | if(input_length)
669 | {
670 | /* Configure publish message */
671 | message_length = mqtt_publish(&publisher, "device1/temp", serial_buffer, input_length);
672 |
673 | /* Send publish message */
674 | ether_tcp_send_data(ethernet, (uint8_t*)network_hardware, test_client, (char*)publisher.publish_msg, message_length);
675 | }
676 | #else
677 |
678 | count++;
679 |
680 | ltoa(count, count_buff);
681 |
682 | console_print(my_console, count_buff);
683 | console_print(my_console, "\n");
684 |
685 | strncpy(copy_publish_message, publish_message, strlen(publish_message));
686 |
687 | strncat(copy_publish_message, count_buff, strlen(count_buff));
688 |
689 | input_length = strlen(copy_publish_message);
690 |
691 | /* Configure publish message */
692 | message_length = mqtt_publish(&publisher, publish_topic, copy_publish_message, input_length);
693 |
694 | /* Send publish message */
695 | ether_tcp_send_data(ethernet, (uint8_t*)network_hardware, test_client, (char*)publisher.publish_msg, message_length);
696 |
697 | memset(copy_publish_message, NULL, strlen(copy_publish_message));
698 | memset(count_buff, NULL, strlen(count_buff));
699 |
700 | if(count >= 10)
701 | {
702 | mqtt_message_state = mqtt_disconnect_state;
703 | break;
704 | }
705 |
706 | #endif
707 |
708 | mqtt_message_state = mqtt_publish_state;
709 |
710 | break;
711 |
712 |
713 | case mqtt_disconnect_state:
714 |
715 | console_print(my_console, "DISCONNECT \n");
716 |
717 | /* Fill DISCONNECT structure */
718 | memset(message,'\0',sizeof(message));
719 |
720 | publisher.disconnect_msg = (void*)message;
721 |
722 | message_length = mqtt_disconnect(&publisher);
723 |
724 | /* Send Disconnect Message */
725 | ether_tcp_send_data(ethernet, (uint8_t*)network_hardware, test_client, (char*)publisher.disconnect_msg, message_length);
726 |
727 | /* Update State */
728 | mqtt_message_state = mqtt_exit_state;
729 |
730 | break;
731 |
732 |
733 | case mqtt_exit_state:
734 |
735 | /* Close the client */
736 | ether_tcp_close(ethernet, (uint8_t*)network_hardware, test_client);
737 |
738 | /* Suspend while loop */
739 | loop_state = FSM_SUSPEND;
740 |
741 | break;
742 |
743 |
744 | default:
745 |
746 | break;
747 |
748 | }
749 |
750 | }
751 |
752 | /* Hold loop */
753 | loop = 1;
754 | while(loop);
755 |
756 | #endif
757 |
758 | return 0;
759 |
760 | }
761 |
--------------------------------------------------------------------------------
/tm4c123gh6pm_startup_ccs.c:
--------------------------------------------------------------------------------
1 | //*****************************************************************************
2 | //
3 | // Startup code for use with TI's Code Composer Studio.
4 | //
5 | // Copyright (c) 2011-2014 Texas Instruments Incorporated. All rights reserved.
6 | // Software License Agreement
7 | //
8 | // Software License Agreement
9 | //
10 | // Texas Instruments (TI) is supplying this software for use solely and
11 | // exclusively on TI's microcontroller products. The software is owned by
12 | // TI and/or its suppliers, and is protected under applicable copyright
13 | // laws. You may not combine this software with "viral" open-source
14 | // software in order to form a larger program.
15 | //
16 | // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
17 | // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
18 | // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 | // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
20 | // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
21 | // DAMAGES, FOR ANY REASON WHATSOEVER.
22 | //
23 | //*****************************************************************************
24 |
25 | #include
26 |
27 | //*****************************************************************************
28 | //
29 | // Forward declaration of the default fault handlers.
30 | //
31 | //*****************************************************************************
32 | void ResetISR(void);
33 | static void NmiSR(void);
34 | static void FaultISR(void);
35 | static void IntDefaultHandler(void);
36 |
37 | //*****************************************************************************
38 | //
39 | // External declaration for the reset handler that is to be called when the
40 | // processor is started
41 | //
42 | //*****************************************************************************
43 | extern void _c_int00(void);
44 |
45 | //*****************************************************************************
46 | //
47 | // Linker variable that marks the top of the stack.
48 | //
49 | //*****************************************************************************
50 | extern uint32_t __STACK_TOP;
51 |
52 | //*****************************************************************************
53 | //
54 | // External declarations for the interrupt handlers used by the application.
55 | //
56 | //*****************************************************************************
57 | // To be added by user
58 |
59 | //*****************************************************************************
60 | //
61 | // The vector table. Note that the proper constructs must be placed on this to
62 | // ensure that it ends up at physical address 0x0000.0000 or at the start of
63 | // the program if located at a start address other than 0.
64 | //
65 | //*****************************************************************************
66 | #pragma DATA_SECTION(g_pfnVectors, ".intvecs")
67 | void (* const g_pfnVectors[])(void) =
68 | {
69 | (void (*)(void))((uint32_t)&__STACK_TOP),
70 | // The initial stack pointer
71 | ResetISR, // The reset handler
72 | NmiSR, // The NMI handler
73 | FaultISR, // The hard fault handler
74 | IntDefaultHandler, // The MPU fault handler
75 | IntDefaultHandler, // The bus fault handler
76 | IntDefaultHandler, // The usage fault handler
77 | 0, // Reserved
78 | 0, // Reserved
79 | 0, // Reserved
80 | 0, // Reserved
81 | IntDefaultHandler, // SVCall handler
82 | IntDefaultHandler, // Debug monitor handler
83 | 0, // Reserved
84 | IntDefaultHandler, // The PendSV handler
85 | IntDefaultHandler, // The SysTick handler
86 | IntDefaultHandler, // GPIO Port A
87 | IntDefaultHandler, // GPIO Port B
88 | IntDefaultHandler, // GPIO Port C
89 | IntDefaultHandler, // GPIO Port D
90 | IntDefaultHandler, // GPIO Port E
91 | IntDefaultHandler, // UART0 Rx and Tx
92 | IntDefaultHandler, // UART1 Rx and Tx
93 | IntDefaultHandler, // SSI0 Rx and Tx
94 | IntDefaultHandler, // I2C0 Master and Slave
95 | IntDefaultHandler, // PWM Fault
96 | IntDefaultHandler, // PWM Generator 0
97 | IntDefaultHandler, // PWM Generator 1
98 | IntDefaultHandler, // PWM Generator 2
99 | IntDefaultHandler, // Quadrature Encoder 0
100 | IntDefaultHandler, // ADC Sequence 0
101 | IntDefaultHandler, // ADC Sequence 1
102 | IntDefaultHandler, // ADC Sequence 2
103 | IntDefaultHandler, // ADC Sequence 3
104 | IntDefaultHandler, // Watchdog timer
105 | IntDefaultHandler, // Timer 0 subtimer A
106 | IntDefaultHandler, // Timer 0 subtimer B
107 | IntDefaultHandler, // Timer 1 subtimer A
108 | IntDefaultHandler, // Timer 1 subtimer B
109 | IntDefaultHandler, // Timer 2 subtimer A
110 | IntDefaultHandler, // Timer 2 subtimer B
111 | IntDefaultHandler, // Analog Comparator 0
112 | IntDefaultHandler, // Analog Comparator 1
113 | IntDefaultHandler, // Analog Comparator 2
114 | IntDefaultHandler, // System Control (PLL, OSC, BO)
115 | IntDefaultHandler, // FLASH Control
116 | IntDefaultHandler, // GPIO Port F
117 | IntDefaultHandler, // GPIO Port G
118 | IntDefaultHandler, // GPIO Port H
119 | IntDefaultHandler, // UART2 Rx and Tx
120 | IntDefaultHandler, // SSI1 Rx and Tx
121 | IntDefaultHandler, // Timer 3 subtimer A
122 | IntDefaultHandler, // Timer 3 subtimer B
123 | IntDefaultHandler, // I2C1 Master and Slave
124 | IntDefaultHandler, // Quadrature Encoder 1
125 | IntDefaultHandler, // CAN0
126 | IntDefaultHandler, // CAN1
127 | 0, // Reserved
128 | 0, // Reserved
129 | IntDefaultHandler, // Hibernate
130 | IntDefaultHandler, // USB0
131 | IntDefaultHandler, // PWM Generator 3
132 | IntDefaultHandler, // uDMA Software Transfer
133 | IntDefaultHandler, // uDMA Error
134 | IntDefaultHandler, // ADC1 Sequence 0
135 | IntDefaultHandler, // ADC1 Sequence 1
136 | IntDefaultHandler, // ADC1 Sequence 2
137 | IntDefaultHandler, // ADC1 Sequence 3
138 | 0, // Reserved
139 | 0, // Reserved
140 | IntDefaultHandler, // GPIO Port J
141 | IntDefaultHandler, // GPIO Port K
142 | IntDefaultHandler, // GPIO Port L
143 | IntDefaultHandler, // SSI2 Rx and Tx
144 | IntDefaultHandler, // SSI3 Rx and Tx
145 | IntDefaultHandler, // UART3 Rx and Tx
146 | IntDefaultHandler, // UART4 Rx and Tx
147 | IntDefaultHandler, // UART5 Rx and Tx
148 | IntDefaultHandler, // UART6 Rx and Tx
149 | IntDefaultHandler, // UART7 Rx and Tx
150 | 0, // Reserved
151 | 0, // Reserved
152 | 0, // Reserved
153 | 0, // Reserved
154 | IntDefaultHandler, // I2C2 Master and Slave
155 | IntDefaultHandler, // I2C3 Master and Slave
156 | IntDefaultHandler, // Timer 4 subtimer A
157 | IntDefaultHandler, // Timer 4 subtimer B
158 | 0, // Reserved
159 | 0, // Reserved
160 | 0, // Reserved
161 | 0, // Reserved
162 | 0, // Reserved
163 | 0, // Reserved
164 | 0, // Reserved
165 | 0, // Reserved
166 | 0, // Reserved
167 | 0, // Reserved
168 | 0, // Reserved
169 | 0, // Reserved
170 | 0, // Reserved
171 | 0, // Reserved
172 | 0, // Reserved
173 | 0, // Reserved
174 | 0, // Reserved
175 | 0, // Reserved
176 | 0, // Reserved
177 | 0, // Reserved
178 | IntDefaultHandler, // Timer 5 subtimer A
179 | IntDefaultHandler, // Timer 5 subtimer B
180 | IntDefaultHandler, // Wide Timer 0 subtimer A
181 | IntDefaultHandler, // Wide Timer 0 subtimer B
182 | IntDefaultHandler, // Wide Timer 1 subtimer A
183 | IntDefaultHandler, // Wide Timer 1 subtimer B
184 | IntDefaultHandler, // Wide Timer 2 subtimer A
185 | IntDefaultHandler, // Wide Timer 2 subtimer B
186 | IntDefaultHandler, // Wide Timer 3 subtimer A
187 | IntDefaultHandler, // Wide Timer 3 subtimer B
188 | IntDefaultHandler, // Wide Timer 4 subtimer A
189 | IntDefaultHandler, // Wide Timer 4 subtimer B
190 | IntDefaultHandler, // Wide Timer 5 subtimer A
191 | IntDefaultHandler, // Wide Timer 5 subtimer B
192 | IntDefaultHandler, // FPU
193 | 0, // Reserved
194 | 0, // Reserved
195 | IntDefaultHandler, // I2C4 Master and Slave
196 | IntDefaultHandler, // I2C5 Master and Slave
197 | IntDefaultHandler, // GPIO Port M
198 | IntDefaultHandler, // GPIO Port N
199 | IntDefaultHandler, // Quadrature Encoder 2
200 | 0, // Reserved
201 | 0, // Reserved
202 | IntDefaultHandler, // GPIO Port P (Summary or P0)
203 | IntDefaultHandler, // GPIO Port P1
204 | IntDefaultHandler, // GPIO Port P2
205 | IntDefaultHandler, // GPIO Port P3
206 | IntDefaultHandler, // GPIO Port P4
207 | IntDefaultHandler, // GPIO Port P5
208 | IntDefaultHandler, // GPIO Port P6
209 | IntDefaultHandler, // GPIO Port P7
210 | IntDefaultHandler, // GPIO Port Q (Summary or Q0)
211 | IntDefaultHandler, // GPIO Port Q1
212 | IntDefaultHandler, // GPIO Port Q2
213 | IntDefaultHandler, // GPIO Port Q3
214 | IntDefaultHandler, // GPIO Port Q4
215 | IntDefaultHandler, // GPIO Port Q5
216 | IntDefaultHandler, // GPIO Port Q6
217 | IntDefaultHandler, // GPIO Port Q7
218 | IntDefaultHandler, // GPIO Port R
219 | IntDefaultHandler, // GPIO Port S
220 | IntDefaultHandler, // PWM 1 Generator 0
221 | IntDefaultHandler, // PWM 1 Generator 1
222 | IntDefaultHandler, // PWM 1 Generator 2
223 | IntDefaultHandler, // PWM 1 Generator 3
224 | IntDefaultHandler // PWM 1 Fault
225 | };
226 |
227 | //*****************************************************************************
228 | //
229 | // This is the code that gets called when the processor first starts execution
230 | // following a reset event. Only the absolutely necessary set is performed,
231 | // after which the application supplied entry() routine is called. Any fancy
232 | // actions (such as making decisions based on the reset cause register, and
233 | // resetting the bits in that register) are left solely in the hands of the
234 | // application.
235 | //
236 | //*****************************************************************************
237 | void
238 | ResetISR(void)
239 | {
240 | //
241 | // Jump to the CCS C initialization routine. This will enable the
242 | // floating-point unit as well, so that does not need to be done here.
243 | //
244 | __asm(" .global _c_int00\n"
245 | " b.w _c_int00");
246 | }
247 |
248 | //*****************************************************************************
249 | //
250 | // This is the code that gets called when the processor receives a NMI. This
251 | // simply enters an infinite loop, preserving the system state for examination
252 | // by a debugger.
253 | //
254 | //*****************************************************************************
255 | static void
256 | NmiSR(void)
257 | {
258 | //
259 | // Enter an infinite loop.
260 | //
261 | while(1)
262 | {
263 | }
264 | }
265 |
266 | //*****************************************************************************
267 | //
268 | // This is the code that gets called when the processor receives a fault
269 | // interrupt. This simply enters an infinite loop, preserving the system state
270 | // for examination by a debugger.
271 | //
272 | //*****************************************************************************
273 | static void
274 | FaultISR(void)
275 | {
276 | //
277 | // Enter an infinite loop.
278 | //
279 | while(1)
280 | {
281 | }
282 | }
283 |
284 | //*****************************************************************************
285 | //
286 | // This is the code that gets called when the processor receives an unexpected
287 | // interrupt. This simply enters an infinite loop, preserving the system state
288 | // for examination by a debugger.
289 | //
290 | //*****************************************************************************
291 | static void
292 | IntDefaultHandler(void)
293 | {
294 | //
295 | // Go into an infinite loop.
296 | //
297 | while(1)
298 | {
299 | }
300 | }
301 |
--------------------------------------------------------------------------------
/wait.c:
--------------------------------------------------------------------------------
1 | // Wait functions
2 | // Jason Losh
3 |
4 | //-----------------------------------------------------------------------------
5 | // Hardware Target
6 | //-----------------------------------------------------------------------------
7 |
8 | // Target uC: TM4C123GH6PM
9 | // System Clock: 40 MHz
10 |
11 | //-----------------------------------------------------------------------------
12 | // Device includes, defines, and assembler directives
13 | //-----------------------------------------------------------------------------
14 |
15 | #include
16 | #include "tm4c123gh6pm.h"
17 | #include "wait.h"
18 |
19 | //-----------------------------------------------------------------------------
20 | // Subroutines
21 | //-----------------------------------------------------------------------------
22 |
23 | // Approximate busy waiting (in units of microseconds), given a 40 MHz system clock
24 | void waitMicrosecond(uint32_t us)
25 | {
26 | __asm("WMS_LOOP0: MOV R1, #6"); // 1
27 | __asm("WMS_LOOP1: SUB R1, #1"); // 6
28 | __asm(" CBZ R1, WMS_DONE1"); // 5+1*3
29 | __asm(" NOP"); // 5
30 | __asm(" NOP"); // 5
31 | __asm(" B WMS_LOOP1"); // 5*2 (speculative, so P=1)
32 | __asm("WMS_DONE1: SUB R0, #1"); // 1
33 | __asm(" CBZ R0, WMS_DONE0"); // 1
34 | __asm(" NOP"); // 1
35 | __asm(" B WMS_LOOP0"); // 1*2 (speculative, so P=1)
36 | __asm("WMS_DONE0:"); // ---
37 | // 40 clocks/us + error
38 | }
39 |
--------------------------------------------------------------------------------
/wait.h:
--------------------------------------------------------------------------------
1 | // Wait functions
2 | // Jason Losh
3 |
4 | //-----------------------------------------------------------------------------
5 | // Hardware Target
6 | //-----------------------------------------------------------------------------
7 |
8 | // Target uC: TM4C123GH6PM
9 | // System Clock: 40 MHz
10 |
11 | #ifndef WAIT_H_
12 | #define WAIT_H_
13 |
14 | //-----------------------------------------------------------------------------
15 | // Subroutines
16 | //-----------------------------------------------------------------------------
17 |
18 | void waitMicrosecond(uint32_t us);
19 |
20 | #endif
21 |
--------------------------------------------------------------------------------