OpenCores
URL https://opencores.org/ocsvn/utosnet/utosnet/trunk

Subversion Repositories utosnet

[/] [utosnet/] [trunk/] [software/] [Digi_app/] [root.cxx] - Blame information for rev 8

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 7 sonicwave
/*
2
* uTosNet_spi Digi application
3
 
4
* root.cxx
5
* File created by:
6
*       Simon Falsig
7
*       University of Southern Denmark
8
*       Copyright 2010
9
*
10
*       This program is free software: you can redistribute it and/or modify
11
*       it under the terms of the GNU Lesser General Public License as published by
12
*       the Free Software Foundation, either version 3 of the License, or
13
*       (at your option) any later version.
14
*
15
*       This program is distributed in the hope that it will be useful,
16
*       but WITHOUT ANY WARRANTY; without even the implied warranty of
17
*       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
*       GNU Lesser General Public License for more details.
19
*
20
*       You should have received a copy of the GNU Lesser General Public License
21
*       along with this program. If not, see <http://www.gnu.org/licenses/>.
22
*/
23
 
24
 
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <tx_api.h>
28
#include <sockapi.h>
29
#include <pthread.h>
30
#include <netoserr.h>
31
#include <string> 
32
#include <appservices.h>
33
#include <wxroot.h>
34
 
35
#include "spi_master_api.h"
36
#include "gpiomux_def.h"
37
#include "appconf.h"
38
#include "iam.hh"
39
#include "Npttypes.h"
40
#include "cliapi.h"                     //Needed for custom cli functions
41
 
42
 
43
#define APP_SPI_MASTER_GPIO_CS      0
44
#define APP_SPI_MASTER_GPIO_CLK     5
45
#define APP_SPI_MASTER_GPIO_RXD     3
46
#define APP_SPI_MASTER_GPIO_TXD     7
47
 
48
 
49
#define MAX_CONNECTIONS 16              //The maximum number of simultaneous connections, may be adjusted
50
#define PACKETSIZE 8                    //Do not change
51
 
52
#define DO_COMMIT_READ_PRE (1<<28)
53
#define DO_READ (1<<27)
54
#define DO_COMMIT_READ_POST (1<<26)
55
#define DO_COMMIT_WRITE_PRE (1<<12)
56
#define DO_WRITE (1<<11)
57
#define DO_COMMIT_WRITE_POST (1<<10)
58
 
59
enum THREAD_STATUS_TYPES
60
{
61
        FREE,
62
        RUNNING,
63
        TERMINATED
64
};
65
 
66
struct sockAddrIn
67
{
68
   short                        sin_family;                             // address family
69
   unsigned short   sin_port;                           // port
70
   struct                       in_addr  sin_addr;              // ip address
71
   char                         sin_zero[8];
72
 
73
   /*
74
    * Adding constructors to sockaddr_in structure
75
    */
76
   sockAddrIn(){sin_family = AF_INET;}
77
 
78
   sockAddrIn(unsigned short port,unsigned long addr = 0)
79
    {
80
       sin_family = AF_INET;
81
       sin_port   = port;
82
       sin_addr.s_addr = addr;
83
   };
84
};
85
 
86
 
87
THREAD_STATUS_TYPES threadInUse[MAX_CONNECTIONS];
88
SOCKET clientSockets[MAX_CONNECTIONS];
89
sockAddrIn* clientSockaddrs[MAX_CONNECTIONS];
90
 
91
/*
92
 * Server thread function
93
 */
94
void netServer(unsigned long port);
95
 
96
 
97
/*
98
 * Network Read thread function
99
 */
100
void netRead(unsigned long threadIndex);
101
 
102
 
103
/*
104
 * FPGA Write thread function
105
 */
106
void fpgaWrite(unsigned long comHandle);
107
 
108
 
109
int readDebug(int fd, int n, char * args[]);            //Custom cli functions
110
int readDebugHelp(int fd, int n, char * args[]);        //
111
 
112
/*
113
 * Set this to 1 to run the system POST tests during startup.
114
 */
115
const int APP_POST = 0;
116
 
117
/*
118
 * Set this to 1 to run the manufacturing burn in tests.
119
 */
120
int APP_BURN_IN_TEST = 0;
121
 
122
/*
123
 * Thread size
124
 */
125
#define STACK_SIZE      4096
126
 
127
/*
128
 * Thread control blocks
129
 */
130
TX_THREAD               net_server;
131
TX_THREAD               fpga_write;
132
TX_THREAD               *net_read[MAX_CONNECTIONS];
133
 
134
/*
135
 * Message queues
136
 */
137
TX_QUEUE                inMsg;
138
 
139
/*
140
 * Global variables
141
 */
142
unsigned int currentReceiverIndex = MAX_CONNECTIONS;
143
char* currentReceiverData;
144
int debug[2];
145
 
146
 
147
 
148
/*
149
 *
150
 *  Function: void applicationTcpDown (void)
151
 *
152
 *  Description:
153
 *
154
 *      This routine will be called by the NET+OS root thread once every
155
 *      clock tick while it is waiting for the TCP/IP stack to come up.
156
 *
157
 *      This routone is called to print the application name and then
158
 *      to print the '.' every second.
159
 *
160
 *      This function will not be called once the stack has started.
161
 *
162
 *      This function uses the global C++ object PrintApplicationDown app_down.
163
 *
164
 *  Parameters:
165
 *
166
 *      none
167
 *
168
 *  Return Values:
169
 *
170
 *      none
171
 *
172
 */
173
extern "C"
174
void applicationTcpDown (void)
175
{
176
}
177
 
178
 
179
 
180
/*
181
 *
182
 *  Function: void applicationStart (void)
183
 *
184
 *  Description:
185
 *
186
 *      This routine is responsible for starting the user application.  It should
187
 *      create any threads or other resources the application needs.
188
 *
189
 *      ThreadX, the NET+OS device drivers, and the TCP/IP stack will be running
190
 *      when this function is called.
191
 *
192
 *      This function uses global C++ object:
193
 *              PrintApplicationDown app_down.
194
 *
195
 *  Parameters:
196
 *
197
 *      none
198
 *
199
 *  Return Values:
200
 *
201
 *      none
202
 *
203
 */
204
 
205
extern "C"
206
void applicationStart (void)
207
 
208
{
209
    void *stack;
210
    char *app_name;
211
    int rc,prio;
212
 
213
#ifdef NETOS_GNU_TOOLS
214
        using namespace std;
215
#endif
216
 
217
        /* Initialize the system services for the application. */
218
        initAppServices();
219
 
220
 
221
        /*
222
         * Create queues for messaging between socket threads and fpga communication thread
223
         */
224
        if(tx_queue_create(&inMsg, (char*)"Incoming Message Queue", TX_1_ULONG , (void*)0x300000, 4*MAX_CONNECTIONS) != SUCCESS)
225
        {
226
                netosFatalError ((char *)"Error creating Incoming Message Queue!", 5, 5);
227
        }
228
 
229
        int i=0;
230
        currentReceiverData = new char[PACKETSIZE+2+32];
231
        while(((int)(&currentReceiverData[i]))%32) i++;         //Buffers used for reading from SPI need to be on a 32 byte boundary
232
        currentReceiverData = &currentReceiverData[i];
233
 
234
        /*
235
         * Add CLI debug stuff
236
         */
237
        NaCliCmd_t userTable;
238
 
239
        userTable.command_name = "rd";
240
        userTable.command_func = readDebug;
241
        userTable.help_func = readDebugHelp;
242
 
243
        naCliAddUserTable(&userTable);
244
 
245
        /*
246
         * Setup SPI communication
247
         */
248
    NAconfigureGPIOpin(APP_SPI_MASTER_GPIO_CS, NA_GPIO_FUNC4_STATE, 0);
249
    NAconfigureGPIOpin(APP_SPI_MASTER_GPIO_CLK, NA_GPIO_FUNC4_STATE, 0);
250
    NAconfigureGPIOpin(APP_SPI_MASTER_GPIO_RXD, NA_GPIO_FUNC4_STATE, 0);
251
    NAconfigureGPIOpin(APP_SPI_MASTER_GPIO_TXD, NA_GPIO_FUNC4_STATE, 0);
252
 
253
        NASpiDeviceConfigType spiDevice0 = {0, NULL, NULL, NA_SPI_MODE2, NA_SPI_MSB, 4000000, 2000, "SPI1"};     //2, 4000000
254
 
255
        NASpiRegisterDevice(&spiDevice0);
256
 
257
        /*
258
         * Start threads
259
         */
260
        prio = 16;
261
 
262
 
263
        stack = malloc (STACK_SIZE);
264
        if (stack == NULL)
265
        {
266
                netosFatalError ((char *)"Unable to allocate thread stack.", 5, 5);
267
        }
268
        rc = tx_thread_create (&net_server,                                                     /* control block for thread*/
269
                                (char *)"Network Server thread",        /* thread name*/
270
                                netServer,                                              /* entry function*/
271
                                50000,                                          /* parameter - port*/
272
                                stack,                                          /* start of stack*/
273
                                STACK_SIZE,                                     /* size of stack*/
274
                                prio,                                           /* priority*/
275
                                prio,                                           /* preemption threshold */
276
                                1,                                              /* time slice threshold*/
277
                                TX_AUTO_START);                                 /* start immediately*/
278
        if (rc != TX_SUCCESS)
279
        {
280
            netosFatalError ((char *)"Unable to create thread.", 5, 5);
281
        }
282
 
283
 
284
 
285
        stack = malloc (STACK_SIZE);
286
        if (stack == NULL)
287
        {
288
                netosFatalError ((char *)"Unable to allocate thread stack.", 5, 5);
289
        }
290
        rc = tx_thread_create (&fpga_write,                                             /* control block for thread*/
291
                                (char *)"Write to FPGA Thread",         /* thread name*/
292
                                fpgaWrite,                                              /* entry function*/
293
                                (unsigned long) 0,                                       /* parameter*/
294
                                stack,                                          /* start of stack*/
295
                                STACK_SIZE,                                     /* size of stack*/
296
                                prio,                                                   /* priority*/
297
                                prio,                                                   /* preemption threshold */
298
                                1,                                              /* time slice threshold*/
299
                                TX_AUTO_START);                                 /* start immediately*/
300
        if (rc != TX_SUCCESS)
301
        {
302
            netosFatalError ((char *)"Unable to create thread.", 5, 5);
303
    }
304
 
305
 
306
        /*
307
         * Necessary threads started, suspend this thread
308
         */
309
        tx_thread_suspend(tx_thread_identify());
310
}
311
 
312
 
313
/*
314
 *
315
 *  Function: void netServer()
316
 *
317
 *  Description:
318
 *
319
 *      This is the netServer thread function.
320
 *              It waits for connections, accepts these, and spawns a new socket
321
 *              and thread to handle them.
322
 *              Old threads are automatically cleaned up when the socket is
323
 *              disconnected.
324
 *
325
 */
326
void netServer(unsigned long port)
327
{
328
    void *stack[MAX_CONNECTIONS];
329
    int rc, prio = 16, currentThreadIndex;
330
    int bufsize = 65536;
331
 
332
 
333
    for(int n=0; n<MAX_CONNECTIONS; n++)
334
    {
335
        threadInUse[n] = FREE;
336
        clientSockaddrs[n] = new sockAddrIn;
337
    }
338
 
339
        SOCKET serverSocket;
340
        serverSocket = socket(AF_INET, SOCK_STREAM, 0);
341
        if(serverSocket == -1)
342
        {
343
                printf("Socket Creation Error %d\n", getErrno());
344
                return;
345
        }
346
 
347
        int error = 0;
348
        const int onValue = 1;
349
        const int offValue = 0;
350
        error += setsockopt(serverSocket, SOL_SOCKET, SO_SNDBUF, (char*)&bufsize, sizeof(bufsize));
351
        error += setsockopt(serverSocket, SOL_SOCKET, SO_RCVBUF, (char*)&bufsize, sizeof(bufsize));
352
        error += setsockopt(serverSocket, SOL_SOCKET, SO_BIO, (char*)&onValue, sizeof(onValue));
353
        error += setsockopt(serverSocket, SOL_SOCKET, SO_NONBLOCK, (char*)&offValue, sizeof(offValue));
354
        if(error != 0)
355
        {
356
                printf("Error setting Socket options %d\n", getErrno());
357
                return;
358
        }
359
 
360
        sockAddrIn sin(50000, INADDR_ANY);
361
        if(bind(serverSocket, (sockaddr *) &sin, sizeof(sin)) == -1)
362
        {
363
                printf("Error binding Socket %d\n", getErrno());
364
                return;
365
        }
366
 
367
        if(listen(serverSocket, MAX_CONNECTIONS) == -1)
368
        {
369
                printf("Error listening on Socket %d\n", getErrno());
370
                return;
371
        }
372
 
373
        int sinClientSize = sizeof(sockAddrIn);
374
 
375
        while(1)
376
        {
377
                for(int n=0; n<MAX_CONNECTIONS; n++)
378
                {
379
                        if(threadInUse[n] == TERMINATED)
380
                        {
381
                                free(stack[n]);
382
                                tx_thread_delete(net_read[n]);
383
                                delete net_read[n];
384
                                threadInUse[n] = FREE;
385
                        }
386
                }
387
 
388
                currentThreadIndex = -1;
389
                for(int n=0; n<MAX_CONNECTIONS; n++)
390
                {
391
                        if(threadInUse[n] == FREE)
392
                        {
393
                                currentThreadIndex = n;
394
                                n = MAX_CONNECTIONS;
395
                        }
396
                }
397
 
398
                if(currentThreadIndex > -1)
399
                {
400
                        if((clientSockets[currentThreadIndex] = accept(serverSocket, (sockaddr*)clientSockaddrs[currentThreadIndex], &sinClientSize)) == -1)
401
                        {
402
                                printf("Error accepting client connection %d\n", getErrno());
403
                                return;
404
                        }
405
                        net_read[currentThreadIndex] = new TX_THREAD;
406
 
407
                        stack[currentThreadIndex] = malloc(STACK_SIZE);
408
                        if (stack[currentThreadIndex] == NULL)
409
                        {
410
                                netosFatalError ((char *)"Unable to allocate thread stack.", 5, 5);
411
                        }
412
                        rc = tx_thread_create (net_read[currentThreadIndex],            /* control block for thread*/
413
                                                (char *)"Network Read thread",          /* thread name*/
414
                                                netRead,                                                /* entry function*/
415
                                                (unsigned long)currentThreadIndex,      /* parameter - port*/
416
                                                stack[currentThreadIndex],                      /* start of stack*/
417
                                                STACK_SIZE,                                     /* size of stack*/
418
                                                prio,                                           /* priority*/
419
                                                prio,                                           /* preemption threshold */
420
                                                1,                                              /* time slice threshold*/
421
                                                TX_AUTO_START);                                 /* start immediately*/
422
                        if (rc != TX_SUCCESS)
423
                        {
424
                            netosFatalError ((char *)"Unable to create thread.", 5, 5);
425
                        }
426
                        else
427
                        {
428
                                threadInUse[currentThreadIndex] = RUNNING;
429
                        }
430
                }
431
 
432
                tx_thread_relinquish();
433
        }
434
}
435
 
436
 
437
/*
438
 *
439
 *  Function: void fpgaWrite()
440
 *
441
 *  Description:
442
 *
443
 *      This is the fpgaWrite thread function.
444
 *              It accepts read/write requests from a message queue, and forwards these
445
 *              to the FPGA over the SPI interface.
446
 *
447
 */
448
void fpgaWrite(unsigned long comHandle)
449
{
450
        char* writeBuffer;
451
        char* readBuffer;
452
        char* temp;
453
        unsigned long currentIndex;
454
        int i=0;
455
 
456
        readBuffer = new char[PACKETSIZE+2+32];
457
 
458
        while(((int)(&readBuffer[i]))%32) i++;
459
 
460
        readBuffer = &readBuffer[i];
461
 
462
        while(1)
463
        {
464
                if(tx_queue_receive(&inMsg, &writeBuffer, TX_NO_WAIT) == TX_SUCCESS)
465
                {
466
                        currentIndex = writeBuffer[PACKETSIZE];
467
                        for(int n=0; n<PACKETSIZE; n++)
468
                        {
469
                                readBuffer[n] = 0;
470
                        }
471
 
472
                        NASpiReadWrite("SPI1", (char*)writeBuffer, (char*)readBuffer, PACKETSIZE);
473
 
474
                        if(((int*)writeBuffer)[0] & DO_COMMIT_READ_PRE)
475
                        {
476
                                ((int*)writeBuffer)[0] &= ~(DO_COMMIT_READ_PRE + DO_COMMIT_WRITE_PRE + DO_WRITE + DO_COMMIT_WRITE_POST);
477
 
478
                                do
479
                                {
480
                                        tx_thread_relinquish();
481
                                        NASpiReadWrite("SPI1", (char*)writeBuffer, (char*)readBuffer, PACKETSIZE);
482
                                        debug[0] = ((int*)readBuffer)[0];
483
                                        debug[1] = ((int*)readBuffer)[1];
484
                                }
485
                                while(((unsigned int*)readBuffer)[0] > 1);
486
                        }
487
 
488
                        if(((int*)writeBuffer)[0] & DO_READ)
489
                        {
490
                                while(currentReceiverIndex != MAX_CONNECTIONS)
491
                                {
492
                                        tx_thread_relinquish();
493
                                }
494
 
495
                                temp = readBuffer;
496
                                readBuffer = currentReceiverData;
497
                                currentReceiverData = temp;
498
                                currentReceiverIndex = currentIndex;
499
                        }
500
                }
501
                tx_thread_relinquish();
502
        }
503
}
504
 
505
/*
506
 *
507
 *  Function: void netRead(unsigned long threadIndex)
508
 *
509
 *  Description:
510
 *
511
 *      This is the netRead thread function.
512
 *              It is spawned for every new connection made to the netServer, and
513
 *              handles the necessary communication.
514
 *
515
 *  Parameters:
516
 *
517
 *              threadIndex     -       The global index of the thread. Used for indexing into
518
 *                                              the global thread status variables.
519
 *
520
 */
521
void netRead(unsigned long threadIndex)
522
{
523
        char* buffer;
524
        int temp;
525
        char backupTemp;
526
 
527
        buffer = new char[PACKETSIZE + 2];
528
        buffer[PACKETSIZE] = '\0';
529
        bool doRead, doWrite;
530
 
531
        while(1)
532
        {
533
        if((temp = recv(clientSockets[threadIndex], buffer, PACKETSIZE, 0)) < 1)
534
        {
535
                        threadInUse[threadIndex] = TERMINATED;
536
                delete [] buffer;
537
                closesocket(clientSockets[threadIndex]);
538
                tx_thread_terminate(tx_thread_identify());
539
        }
540
        else
541
        {
542
                for(int n=0; n<(PACKETSIZE/4); n++)
543
                {
544
                        backupTemp = buffer[n*4];
545
                        buffer[n*4] = buffer[n*4+3];
546
                        buffer[n*4+3] = backupTemp;
547
                        backupTemp = buffer[n*4+2];
548
                        buffer[n*4+2] = buffer[n*4+1];
549
                        buffer[n*4+1] = backupTemp;
550
                }
551
 
552
                buffer[PACKETSIZE+1] = '\0';
553
                        buffer[PACKETSIZE] = threadIndex;
554
 
555
                        doRead = ((int*)buffer)[0] & DO_READ;
556
                        doWrite = ((int*)buffer)[0] & DO_WRITE;
557
 
558
                        if(doWrite && (temp < 8))
559
                        {
560
                                ((int*)buffer)[0] &= ~(DO_COMMIT_WRITE_PRE + DO_WRITE + DO_COMMIT_WRITE_POST);
561
                        }
562
 
563
                        if(!doRead)
564
                        {
565
                                ((int*)buffer)[0] &= ~(DO_COMMIT_READ_PRE);
566
                        }
567
 
568
                        tx_queue_send(&inMsg, &buffer, TX_NO_WAIT);
569
 
570
                        if(doRead)
571
                        {
572
                                while(currentReceiverIndex != threadIndex)
573
                                {
574
                                        tx_thread_relinquish();
575
                                }
576
 
577
                        backupTemp = (&(currentReceiverData[4]))[0];
578
                        (&(currentReceiverData[4]))[0] = (&(currentReceiverData[4]))[3];
579
                        (&(currentReceiverData[4]))[3] = backupTemp;
580
                        backupTemp = (&(currentReceiverData[4]))[2];
581
                        (&(currentReceiverData[4]))[2] = (&(currentReceiverData[4]))[1];
582
                        (&(currentReceiverData[4]))[1] = backupTemp;
583
 
584
                                send(clientSockets[threadIndex], (&(currentReceiverData[4])), 4, 0);
585
 
586
                                currentReceiverIndex = MAX_CONNECTIONS;
587
                        }
588
        }
589
 
590
                tx_thread_relinquish();
591
        }
592
}
593
 
594
 
595
int readDebug(int fd, int n, char * args[])
596
{
597
        naCliPrintf(fd, "Read values: %.8x  |  %.8x\n\r", debug[0], debug[1]);
598
 
599
        return 0;
600
}
601
 
602
int readDebugHelp(int fd, int n, char * args[])
603
{
604
        naCliPrintf(fd, "Prints the six first integers in the read-array from the SPI transfer");
605
 
606
        return 0;
607
}
608
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.