1+ #include < Arduino.h>
2+ #include < Arduino_DebugUtils.h>
3+ #include < IRQManager.h>
4+ #include < regex>
5+ #include < utils.h>
6+
7+ // #define CNETIF_STATS_ENABLED
8+ // #include "CNetifStats.h"
9+
10+ #ifdef CNETIF_STATS_ENABLED
11+ #define STATS_BUFFER_SIZE 1000
12+ char cnetif_stats_buffer[STATS_BUFFER_SIZE];
13+ // netif_stats _stats;
14+ #endif // CNETIF_STATS_ENABLED
15+
16+ #include < EthernetC33.h>
17+ #include < lwipClient.h>
18+
19+ #define CHECK_PAYLOAD
20+
21+ /* --------------------------------------- */
22+ void timer_cb (timer_callback_args_t *arg);
23+ void application ();
24+ void dump_buffer (uint8_t * b, uint32_t len, uint8_t blocks=4 , uint8_t cols=16 );
25+ void dump_buffer_char (uint8_t * b, uint32_t len);
26+ uint64_t debug_start;
27+ /* --------------------------------------- */
28+
29+ void setup () {
30+ Serial.begin (115200 );
31+ while (!Serial);
32+
33+ Serial.println (" Renesas file download example" );
34+
35+ IPAddress ip (192 , 168 , 10 , 130 );
36+ IPAddress gw (192 , 168 , 10 , 1 );
37+ IPAddress nm (255 , 255 , 255 , 0 );
38+
39+ DEBUG_INFO (" Setting up netif" );
40+ Ethernet.begin (ip, nm, gw);
41+ // Ethernet.begin();
42+
43+ DEBUG_INFO (" Begin of reception\n\n " );
44+ debug_start = millis ();
45+ }
46+
47+ uint32_t counter=0 ;
48+ void loop () {
49+ // __disable_irq();
50+ uint32_t start = micros ();
51+ #ifndef LWIP_USE_TIMER
52+ CLwipIf::getInstance ().task ();
53+ #endif
54+ // Handle application FSM
55+ application ();
56+
57+ if (millis () - debug_start > 3000 ) { // print the debug _stats every x second
58+ // DEBUG_INFO("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
59+ DEBUG_INFO (" time: %12ums" , millis ());
60+ // DEBUG_INFO("memory: %12u bytes \tmin: %12u bytes \tmax: %12u bytes",
61+ // memory_used, memory_used_min, memory_used_max);
62+ DEBUG_INFO (" loop counter %u\n " , counter);
63+ // application_report();
64+
65+ #ifdef CNETIF_STATS_ENABLED
66+ netif_stats_sprintf (cnetif_stats_buffer, Ethernet.stats , STATS_BUFFER_SIZE, (8 *1e6 )/(1 <<20 ), " Mbit/s" );
67+ // __disable_irq();
68+ arduino::lock ();
69+ NETIF_STATS_RESET_AVERAGES (Ethernet.stats );
70+ // __enable_irq();
71+ arduino::unlock ();
72+
73+ DEBUG_INFO (cnetif_stats_buffer);
74+ #endif // CNETIF_STATS_ENABLED
75+ // DEBUG_INFO("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
76+
77+ counter = 0 ;
78+ // reset some counters
79+ debug_start = millis ();
80+ }
81+ counter++;
82+ }
83+
84+ // Application level Stuff
85+ enum app_state_t : uint8_t {
86+ APP_STATE_NONE = 0 ,
87+ APP_STATE_LINK_UP,
88+ APP_STATE_LINK_DOWN,
89+ APP_STATE_IFACE_UP,
90+ APP_STATE_CONNECTING,
91+ APP_STATE_CONNECTED,
92+ APP_STATE_SEND,
93+ APP_STATE_RECEIVE,
94+ APP_STATE_ERROR,
95+ APP_STATE_RESET
96+ };
97+
98+ static const char * state_strings[] = {
99+ " APP_STATE_NONE" ,
100+ " APP_STATE_LINK_UP" ,
101+ " APP_STATE_LINK_DOWN" ,
102+ " APP_STATE_IFACE_UP" ,
103+ " APP_STATE_CONNECTING" ,
104+ " APP_STATE_CONNECTED" ,
105+ " APP_STATE_SEND" ,
106+ " APP_STATE_RECEIVE" ,
107+ " APP_STATE_ERROR" ,
108+ " APP_STATE_RESET"
109+ };
110+
111+ #define APP_BUFFER_SIZE 1 *1024
112+
113+ typedef uint32_t counter_t ;
114+
115+ struct App {
116+ app_state_t current_state=APP_STATE_NONE;
117+ app_state_t prev_state=APP_STATE_NONE;
118+
119+ lwipClient *tcp_client;
120+ uint16_t port = 2000 ;
121+ IPAddress server_ip = IPAddress(192 , 168 , 10 , 250 );
122+
123+ counter_t counter;
124+ uint8_t buffer[APP_BUFFER_SIZE];
125+
126+ size_t file_length=0 ;
127+ size_t downloaded_bytes=0 ;
128+ std::string http_header;
129+
130+ // stats related variables
131+ uint32_t start = 0 ;
132+ uint32_t speed_start = 0 ;
133+ uint32_t speed_bytes = 0 ;
134+
135+ // payload verification parameters
136+ uint32_t payload_verify_offset=0 ;
137+ uint8_t payload_verify_excess[4 ]={}; // this should be 3, but there are bugs
138+ uint8_t payload_verify_excess_len=0 ;
139+ uint32_t last_value=0 ;
140+ } app;
141+
142+ void init_app (struct App & app) {
143+ app.file_length = 0 ;
144+ app.http_header = " " ;
145+ app.downloaded_bytes = 0 ;
146+ app.start = 0 ;
147+ app.payload_verify_excess_len = 0 ;
148+ app.payload_verify_offset = 0 ;
149+ app.last_value =0 ;
150+ app.speed_bytes = 0 ;
151+ app.counter = 0 ;
152+ }
153+
154+ void reset_app (struct App & app) {
155+ init_app (app);
156+
157+ if (app.tcp_client != nullptr ) {
158+ app.tcp_client ->stop ();
159+ // delete app.tcp_client;
160+ }
161+ }
162+
163+ void application () {
164+ bool found = false ;
165+ uint16_t bytes_read=0 ;
166+
167+ switch (app.current_state ) {
168+ case APP_STATE_NONE:
169+ init_app (app);
170+
171+ // TODO we are not handling link connection and disconnection
172+ app.prev_state = app.current_state ;
173+ app.current_state = APP_STATE_LINK_UP;
174+ DEBUG_INFO (" State changed: to %s, from %s" ,
175+ state_strings[app.current_state ],
176+ state_strings[app.prev_state ]);
177+ break ;
178+
179+ case APP_STATE_LINK_UP:
180+ if (Ethernet.isDhcpAcquired ()) {
181+ app.prev_state = app.current_state ;
182+ app.current_state = APP_STATE_IFACE_UP;
183+ DEBUG_INFO (" State changed: to %s, from %s" ,
184+ state_strings[app.current_state ],
185+ state_strings[app.prev_state ]);
186+ }
187+ break ;
188+ case APP_STATE_IFACE_UP:
189+ // The link is up we connect to the server
190+ app.tcp_client = new lwipClient;
191+
192+ // Connection details:
193+ app.tcp_client ->connect (app.server_ip , app.port );
194+
195+ app.prev_state = app.current_state ;
196+ app.current_state = APP_STATE_CONNECTING;
197+ DEBUG_INFO (" State changed: to %s, from %s" ,
198+ state_strings[app.current_state ],
199+ state_strings[app.prev_state ]);
200+ break ;
201+
202+ case APP_STATE_CONNECTING:
203+ // do nothing, until the TCP connection is established
204+ // TODO handle timeout for connection and go to error state
205+ if (app.tcp_client ->connected ()) {
206+ app.prev_state = app.current_state ;
207+ app.current_state = APP_STATE_SEND;
208+ DEBUG_INFO (" State changed: to %s, from %s" ,
209+ state_strings[app.current_state ],
210+ state_strings[app.prev_state ]);
211+ }
212+
213+ break ;
214+
215+ case APP_STATE_CONNECTED:
216+ app.start = millis ();
217+ app.speed_start = app.start ;
218+
219+ app.prev_state = app.current_state ;
220+ app.current_state = APP_STATE_SEND;
221+ DEBUG_INFO (" State changed: to %s, from %s" ,
222+ state_strings[app.current_state ],
223+ state_strings[app.prev_state ]);
224+ break ;
225+ case APP_STATE_SEND: {
226+ int res = app.tcp_client ->write ((uint8_t *)&app.counter , sizeof (counter_t ));
227+ DEBUG_INFO (" counter sent, value 0x%08X, res: %d" , app.counter , res);
228+
229+ if (res == sizeof (counter_t )) {
230+ app.counter ++;
231+ app.prev_state = app.current_state ;
232+ app.current_state = APP_STATE_RECEIVE;
233+ // DEBUG_INFO("State changed: to %s, from %s",
234+ // state_strings[app.current_state],
235+ // state_strings[app.prev_state]);
236+ }
237+ break ;
238+ }
239+ case APP_STATE_RECEIVE: {
240+ counter_t read_counter;
241+ bytes_read = app.tcp_client ->read ((uint8_t *)&read_counter, sizeof (counter_t ));
242+
243+ if (bytes_read == sizeof (counter_t )) {
244+ DEBUG_INFO (" counter echoed, value 0x%08X" , read_counter);
245+
246+ app.prev_state = app.current_state ;
247+ app.current_state = APP_STATE_SEND;
248+ // DEBUG_INFO("State changed: to %s, from %s",
249+ // state_strings[app.current_state],
250+ // state_strings[app.prev_state]);
251+ }
252+ break ;
253+ }
254+ case APP_STATE_ERROR:
255+ // The app reached an expected error state
256+ // TODO report this state and go in the default, status not defined handler to reset the state
257+ case APP_STATE_RESET:
258+ // in this state we reset the application and we start back from the beginning
259+
260+ reset_app (app);
261+
262+ app.prev_state = app.current_state ;
263+ app.current_state = APP_STATE_IFACE_UP;
264+ DEBUG_INFO (" State changed: to %s, from %s" ,
265+ state_strings[app.current_state ],
266+ state_strings[app.prev_state ]);
267+ break ;
268+ }
269+ }
270+
271+ // Utility functions
272+ void dump_buffer (uint8_t * b, uint32_t len, uint8_t blocks, uint8_t cols) {
273+
274+ // TODO make sure blocks is less that cols
275+ Serial.println (" BUFFER >>>>>>>" );
276+ for (uint8_t *p=b; p<b+len; p++) {
277+ if (p == nullptr ) {
278+ break ;
279+ }
280+ if (*p < 0x10 ) {
281+ Serial.print (0 );
282+ }
283+ Serial.print (*p, HEX);
284+
285+ if (cols != 0 && ((p-b)+1 ) % blocks == 0 && ((p-b)+1 ) % cols != 0 ){
286+ Serial.print (" " );
287+ }
288+ if (cols != 0 && ((p-b)+1 ) % cols == 0 ){
289+ Serial.println ();
290+ }
291+ }
292+ Serial.println (" \n BUFFER <<<<<<<" );
293+ }
294+
295+ void dump_buffer_char (uint8_t * b, uint32_t len) {
296+ Serial.println (" BUFFER_CHAR >>>>>>>" );
297+ for (uint8_t *p=b; p<b+len; p++) {
298+ Serial.print ((char )*p);
299+ }
300+ Serial.println (" \n BUFFER_CHAR <<<<<<<" );
301+ }
0 commit comments