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

Subversion Repositories utosnet

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /utosnet
    from Rev 6 to Rev 7
    Reverse comparison

Rev 6 → Rev 7

/trunk/software/Digi_app/root.cxx
0,0 → 1,608
/*
* uTosNet_spi Digi application
 
* root.cxx
* File created by:
* Simon Falsig
* University of Southern Denmark
* Copyright 2010
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <tx_api.h>
#include <sockapi.h>
#include <pthread.h>
#include <netoserr.h>
#include <string>
#include <appservices.h>
#include <wxroot.h>
 
#include "spi_master_api.h"
#include "gpiomux_def.h"
#include "appconf.h"
#include "iam.hh"
#include "Npttypes.h"
#include "cliapi.h" //Needed for custom cli functions
 
 
#define APP_SPI_MASTER_GPIO_CS 0
#define APP_SPI_MASTER_GPIO_CLK 5
#define APP_SPI_MASTER_GPIO_RXD 3
#define APP_SPI_MASTER_GPIO_TXD 7
 
 
#define MAX_CONNECTIONS 16 //The maximum number of simultaneous connections, may be adjusted
#define PACKETSIZE 8 //Do not change
 
#define DO_COMMIT_READ_PRE (1<<28)
#define DO_READ (1<<27)
#define DO_COMMIT_READ_POST (1<<26)
#define DO_COMMIT_WRITE_PRE (1<<12)
#define DO_WRITE (1<<11)
#define DO_COMMIT_WRITE_POST (1<<10)
 
enum THREAD_STATUS_TYPES
{
FREE,
RUNNING,
TERMINATED
};
 
struct sockAddrIn
{
short sin_family; // address family
unsigned short sin_port; // port
struct in_addr sin_addr; // ip address
char sin_zero[8];
 
/*
* Adding constructors to sockaddr_in structure
*/
sockAddrIn(){sin_family = AF_INET;}
 
sockAddrIn(unsigned short port,unsigned long addr = 0)
{
sin_family = AF_INET;
sin_port = port;
sin_addr.s_addr = addr;
};
};
 
 
THREAD_STATUS_TYPES threadInUse[MAX_CONNECTIONS];
SOCKET clientSockets[MAX_CONNECTIONS];
sockAddrIn* clientSockaddrs[MAX_CONNECTIONS];
 
/*
* Server thread function
*/
void netServer(unsigned long port);
 
 
/*
* Network Read thread function
*/
void netRead(unsigned long threadIndex);
 
 
/*
* FPGA Write thread function
*/
void fpgaWrite(unsigned long comHandle);
 
 
int readDebug(int fd, int n, char * args[]); //Custom cli functions
int readDebugHelp(int fd, int n, char * args[]); //
 
/*
* Set this to 1 to run the system POST tests during startup.
*/
const int APP_POST = 0;
 
/*
* Set this to 1 to run the manufacturing burn in tests.
*/
int APP_BURN_IN_TEST = 0;
 
/*
* Thread size
*/
#define STACK_SIZE 4096
 
/*
* Thread control blocks
*/
TX_THREAD net_server;
TX_THREAD fpga_write;
TX_THREAD *net_read[MAX_CONNECTIONS];
 
/*
* Message queues
*/
TX_QUEUE inMsg;
 
/*
* Global variables
*/
unsigned int currentReceiverIndex = MAX_CONNECTIONS;
char* currentReceiverData;
int debug[2];
 
 
 
/*
*
* Function: void applicationTcpDown (void)
*
* Description:
*
* This routine will be called by the NET+OS root thread once every
* clock tick while it is waiting for the TCP/IP stack to come up.
*
* This routone is called to print the application name and then
* to print the '.' every second.
*
* This function will not be called once the stack has started.
*
* This function uses the global C++ object PrintApplicationDown app_down.
*
* Parameters:
*
* none
*
* Return Values:
*
* none
*
*/
extern "C"
void applicationTcpDown (void)
{
}
 
 
 
/*
*
* Function: void applicationStart (void)
*
* Description:
*
* This routine is responsible for starting the user application. It should
* create any threads or other resources the application needs.
*
* ThreadX, the NET+OS device drivers, and the TCP/IP stack will be running
* when this function is called.
*
* This function uses global C++ object:
* PrintApplicationDown app_down.
*
* Parameters:
*
* none
*
* Return Values:
*
* none
*
*/
 
extern "C"
void applicationStart (void)
 
{
void *stack;
char *app_name;
int rc,prio;
 
#ifdef NETOS_GNU_TOOLS
using namespace std;
#endif
 
/* Initialize the system services for the application. */
initAppServices();
/*
* Create queues for messaging between socket threads and fpga communication thread
*/
if(tx_queue_create(&inMsg, (char*)"Incoming Message Queue", TX_1_ULONG , (void*)0x300000, 4*MAX_CONNECTIONS) != SUCCESS)
{
netosFatalError ((char *)"Error creating Incoming Message Queue!", 5, 5);
}
 
int i=0;
currentReceiverData = new char[PACKETSIZE+2+32];
while(((int)(&currentReceiverData[i]))%32) i++; //Buffers used for reading from SPI need to be on a 32 byte boundary
currentReceiverData = &currentReceiverData[i];
 
/*
* Add CLI debug stuff
*/
NaCliCmd_t userTable;
userTable.command_name = "rd";
userTable.command_func = readDebug;
userTable.help_func = readDebugHelp;
naCliAddUserTable(&userTable);
/*
* Setup SPI communication
*/
NAconfigureGPIOpin(APP_SPI_MASTER_GPIO_CS, NA_GPIO_FUNC4_STATE, 0);
NAconfigureGPIOpin(APP_SPI_MASTER_GPIO_CLK, NA_GPIO_FUNC4_STATE, 0);
NAconfigureGPIOpin(APP_SPI_MASTER_GPIO_RXD, NA_GPIO_FUNC4_STATE, 0);
NAconfigureGPIOpin(APP_SPI_MASTER_GPIO_TXD, NA_GPIO_FUNC4_STATE, 0);
 
NASpiDeviceConfigType spiDevice0 = {0, NULL, NULL, NA_SPI_MODE2, NA_SPI_MSB, 4000000, 2000, "SPI1"}; //2, 4000000
 
NASpiRegisterDevice(&spiDevice0);
 
/*
* Start threads
*/
prio = 16;
 
 
stack = malloc (STACK_SIZE);
if (stack == NULL)
{
netosFatalError ((char *)"Unable to allocate thread stack.", 5, 5);
}
rc = tx_thread_create (&net_server, /* control block for thread*/
(char *)"Network Server thread", /* thread name*/
netServer, /* entry function*/
50000, /* parameter - port*/
stack, /* start of stack*/
STACK_SIZE, /* size of stack*/
prio, /* priority*/
prio, /* preemption threshold */
1, /* time slice threshold*/
TX_AUTO_START); /* start immediately*/
if (rc != TX_SUCCESS)
{
netosFatalError ((char *)"Unable to create thread.", 5, 5);
}
 
 
 
stack = malloc (STACK_SIZE);
if (stack == NULL)
{
netosFatalError ((char *)"Unable to allocate thread stack.", 5, 5);
}
rc = tx_thread_create (&fpga_write, /* control block for thread*/
(char *)"Write to FPGA Thread", /* thread name*/
fpgaWrite, /* entry function*/
(unsigned long) 0, /* parameter*/
stack, /* start of stack*/
STACK_SIZE, /* size of stack*/
prio, /* priority*/
prio, /* preemption threshold */
1, /* time slice threshold*/
TX_AUTO_START); /* start immediately*/
if (rc != TX_SUCCESS)
{
netosFatalError ((char *)"Unable to create thread.", 5, 5);
}
 
 
/*
* Necessary threads started, suspend this thread
*/
tx_thread_suspend(tx_thread_identify());
}
 
 
/*
*
* Function: void netServer()
*
* Description:
*
* This is the netServer thread function.
* It waits for connections, accepts these, and spawns a new socket
* and thread to handle them.
* Old threads are automatically cleaned up when the socket is
* disconnected.
*
*/
void netServer(unsigned long port)
{
void *stack[MAX_CONNECTIONS];
int rc, prio = 16, currentThreadIndex;
int bufsize = 65536;
 
for(int n=0; n<MAX_CONNECTIONS; n++)
{
threadInUse[n] = FREE;
clientSockaddrs[n] = new sockAddrIn;
}
SOCKET serverSocket;
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if(serverSocket == -1)
{
printf("Socket Creation Error %d\n", getErrno());
return;
}
 
int error = 0;
const int onValue = 1;
const int offValue = 0;
error += setsockopt(serverSocket, SOL_SOCKET, SO_SNDBUF, (char*)&bufsize, sizeof(bufsize));
error += setsockopt(serverSocket, SOL_SOCKET, SO_RCVBUF, (char*)&bufsize, sizeof(bufsize));
error += setsockopt(serverSocket, SOL_SOCKET, SO_BIO, (char*)&onValue, sizeof(onValue));
error += setsockopt(serverSocket, SOL_SOCKET, SO_NONBLOCK, (char*)&offValue, sizeof(offValue));
if(error != 0)
{
printf("Error setting Socket options %d\n", getErrno());
return;
}
sockAddrIn sin(50000, INADDR_ANY);
if(bind(serverSocket, (sockaddr *) &sin, sizeof(sin)) == -1)
{
printf("Error binding Socket %d\n", getErrno());
return;
}
if(listen(serverSocket, MAX_CONNECTIONS) == -1)
{
printf("Error listening on Socket %d\n", getErrno());
return;
}
int sinClientSize = sizeof(sockAddrIn);
 
while(1)
{
for(int n=0; n<MAX_CONNECTIONS; n++)
{
if(threadInUse[n] == TERMINATED)
{
free(stack[n]);
tx_thread_delete(net_read[n]);
delete net_read[n];
threadInUse[n] = FREE;
}
}
currentThreadIndex = -1;
for(int n=0; n<MAX_CONNECTIONS; n++)
{
if(threadInUse[n] == FREE)
{
currentThreadIndex = n;
n = MAX_CONNECTIONS;
}
}
if(currentThreadIndex > -1)
{
if((clientSockets[currentThreadIndex] = accept(serverSocket, (sockaddr*)clientSockaddrs[currentThreadIndex], &sinClientSize)) == -1)
{
printf("Error accepting client connection %d\n", getErrno());
return;
}
net_read[currentThreadIndex] = new TX_THREAD;
stack[currentThreadIndex] = malloc(STACK_SIZE);
if (stack[currentThreadIndex] == NULL)
{
netosFatalError ((char *)"Unable to allocate thread stack.", 5, 5);
}
rc = tx_thread_create (net_read[currentThreadIndex], /* control block for thread*/
(char *)"Network Read thread", /* thread name*/
netRead, /* entry function*/
(unsigned long)currentThreadIndex, /* parameter - port*/
stack[currentThreadIndex], /* start of stack*/
STACK_SIZE, /* size of stack*/
prio, /* priority*/
prio, /* preemption threshold */
1, /* time slice threshold*/
TX_AUTO_START); /* start immediately*/
if (rc != TX_SUCCESS)
{
netosFatalError ((char *)"Unable to create thread.", 5, 5);
}
else
{
threadInUse[currentThreadIndex] = RUNNING;
}
}
tx_thread_relinquish();
}
}
 
 
/*
*
* Function: void fpgaWrite()
*
* Description:
*
* This is the fpgaWrite thread function.
* It accepts read/write requests from a message queue, and forwards these
* to the FPGA over the SPI interface.
*
*/
void fpgaWrite(unsigned long comHandle)
{
char* writeBuffer;
char* readBuffer;
char* temp;
unsigned long currentIndex;
int i=0;
readBuffer = new char[PACKETSIZE+2+32];
while(((int)(&readBuffer[i]))%32) i++;
readBuffer = &readBuffer[i];
while(1)
{
if(tx_queue_receive(&inMsg, &writeBuffer, TX_NO_WAIT) == TX_SUCCESS)
{
currentIndex = writeBuffer[PACKETSIZE];
for(int n=0; n<PACKETSIZE; n++)
{
readBuffer[n] = 0;
}
 
NASpiReadWrite("SPI1", (char*)writeBuffer, (char*)readBuffer, PACKETSIZE);
 
if(((int*)writeBuffer)[0] & DO_COMMIT_READ_PRE)
{
((int*)writeBuffer)[0] &= ~(DO_COMMIT_READ_PRE + DO_COMMIT_WRITE_PRE + DO_WRITE + DO_COMMIT_WRITE_POST);
 
do
{
tx_thread_relinquish();
NASpiReadWrite("SPI1", (char*)writeBuffer, (char*)readBuffer, PACKETSIZE);
debug[0] = ((int*)readBuffer)[0];
debug[1] = ((int*)readBuffer)[1];
}
while(((unsigned int*)readBuffer)[0] > 1);
}
 
if(((int*)writeBuffer)[0] & DO_READ)
{
while(currentReceiverIndex != MAX_CONNECTIONS)
{
tx_thread_relinquish();
}
 
temp = readBuffer;
readBuffer = currentReceiverData;
currentReceiverData = temp;
currentReceiverIndex = currentIndex;
}
}
tx_thread_relinquish();
}
}
 
/*
*
* Function: void netRead(unsigned long threadIndex)
*
* Description:
*
* This is the netRead thread function.
* It is spawned for every new connection made to the netServer, and
* handles the necessary communication.
*
* Parameters:
*
* threadIndex - The global index of the thread. Used for indexing into
* the global thread status variables.
*
*/
void netRead(unsigned long threadIndex)
{
char* buffer;
int temp;
char backupTemp;
buffer = new char[PACKETSIZE + 2];
buffer[PACKETSIZE] = '\0';
bool doRead, doWrite;
while(1)
{
if((temp = recv(clientSockets[threadIndex], buffer, PACKETSIZE, 0)) < 1)
{
threadInUse[threadIndex] = TERMINATED;
delete [] buffer;
closesocket(clientSockets[threadIndex]);
tx_thread_terminate(tx_thread_identify());
}
else
{
for(int n=0; n<(PACKETSIZE/4); n++)
{
backupTemp = buffer[n*4];
buffer[n*4] = buffer[n*4+3];
buffer[n*4+3] = backupTemp;
backupTemp = buffer[n*4+2];
buffer[n*4+2] = buffer[n*4+1];
buffer[n*4+1] = backupTemp;
}
buffer[PACKETSIZE+1] = '\0';
buffer[PACKETSIZE] = threadIndex;
 
doRead = ((int*)buffer)[0] & DO_READ;
doWrite = ((int*)buffer)[0] & DO_WRITE;
if(doWrite && (temp < 8))
{
((int*)buffer)[0] &= ~(DO_COMMIT_WRITE_PRE + DO_WRITE + DO_COMMIT_WRITE_POST);
}
if(!doRead)
{
((int*)buffer)[0] &= ~(DO_COMMIT_READ_PRE);
}
tx_queue_send(&inMsg, &buffer, TX_NO_WAIT);
 
if(doRead)
{
while(currentReceiverIndex != threadIndex)
{
tx_thread_relinquish();
}
 
backupTemp = (&(currentReceiverData[4]))[0];
(&(currentReceiverData[4]))[0] = (&(currentReceiverData[4]))[3];
(&(currentReceiverData[4]))[3] = backupTemp;
backupTemp = (&(currentReceiverData[4]))[2];
(&(currentReceiverData[4]))[2] = (&(currentReceiverData[4]))[1];
(&(currentReceiverData[4]))[1] = backupTemp;
 
send(clientSockets[threadIndex], (&(currentReceiverData[4])), 4, 0);
 
currentReceiverIndex = MAX_CONNECTIONS;
}
}
tx_thread_relinquish();
}
}
 
 
int readDebug(int fd, int n, char * args[])
{
naCliPrintf(fd, "Read values: %.8x | %.8x\n\r", debug[0], debug[1]);
return 0;
}
 
int readDebugHelp(int fd, int n, char * args[])
{
naCliPrintf(fd, "Prints the six first integers in the read-array from the SPI transfer");
return 0;
}
 
/trunk/software/Digi_app/readme.txt
0,0 → 1,81
 
uTosNet_spi Digi application, readme.txt
 
Simon Falsig
University of Southern Denmark
Copyright 2010
 
This file is part of the uTosNet_spi Digi application
 
The uTosNet_spi Digi application is free software: you can redistribute it
and/or modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
 
The uTosNet_spi Digi application is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public License
along with the uTosNet_spi Digi application. If not, see
<http://www.gnu.org/licenses/>.
 
 
******************************************
* Description
******************************************
The uTosNet_spi Digi application is meant for use with the Ethernet/SPI
version of uTosNet. It provides the server application that should run
on the Digi Connect ME 9210 microcontroller module, in order for it to
work with the uTosNet_spi FPGA module and PC application.
 
******************************************
* Building
******************************************
Use the Digi IDE to create a new project, and use the accompanying
root.cxx file as the main file. Then build and download it according
to standard Digi procedures.
 
******************************************
* Usage
******************************************
The server application listens on port 50000, and uses a binary protocol.
It accepts the following kinds of packets:
(for all packets bit 31 is MSB, all unspecified bits should be '0')
 
 
- Read request (32 bits):
- Bit 29: Set to '1'
- Bit 25-16: Set to read address
- Set all others to '0'
 
Response (32 bits):
- Bit 31-0: Contains read data
 
 
- Write request (2x32 bits):
First 32 bits:
- Bit 11: Set to '1'
- Bit 9-0: Set to write address
Second 32 bits:
- Bit 31-0: Set to write data
 
Response: None
 
 
- Combined read/write (2x32 bits)
First 32 bits:
- Bit 29: Set to '1'
- Bit 25-16: Set to read address
- Bit 11: Set to '1'
- Bit 9-0: Set to write address
Second 32 bits:
- Bit 31-0: Set to write data
 
Response (32 bits):
- Bit 31-0: Contains read data
 
******************************************
* End of file
******************************************

powered by: WebSVN 2.1.0

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