1
0
mirror of git://projects.qi-hardware.com/nn-usb-fpga.git synced 2025-04-21 12:27:27 +03:00

Adding plasma example

This commit is contained in:
Carlos Camargo
2010-04-21 20:01:38 -05:00
parent f80360a678
commit 22c469585b
59 changed files with 18082 additions and 0 deletions

537
plasma/kernel/dll.h Normal file
View File

@@ -0,0 +1,537 @@
/*--------------------------------------------------------------------
* TITLE: Plasma Dynamic Link Library
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
* DATE CREATED: 4/4/08
* FILENAME: dll.h
* PROJECT: Plasma CPU core
* COPYRIGHT: Software placed into the public domain by the author.
* Software 'as is' without warranty. Author liable for nothing.
* DESCRIPTION:
* Dynamic Link Library
*--------------------------------------------------------------------*/
#ifndef __DLL_H__
#define __DLL_H__
#define INCLUDE_FILESYS
#include "rtos.h"
#include "tcpip.h"
typedef void *(*DllFunc)();
// Included by Plasma Kernel to create array of function pointers
#ifdef DLL_SETUP
void *DllDummy(void) { printf("Dummy"); return NULL; }
const DllFunc DllFuncList[] = {
(DllFunc)strcpy,
(DllFunc)strncpy,
(DllFunc)strcat,
(DllFunc)strncat,
(DllFunc)strcmp,
(DllFunc)strncmp,
(DllFunc)strstr,
(DllFunc)strlen,
(DllFunc)memcpy,
(DllFunc)memmove,
(DllFunc)memcmp,
(DllFunc)memset,
(DllFunc)abs,
(DllFunc)rand,
(DllFunc)srand,
(DllFunc)strtol,
(DllFunc)atoi,
(DllFunc)itoa,
(DllFunc)sprintf,
(DllFunc)sscanf,
#ifdef INCLUDE_DUMP
(DllFunc)dump,
#else //INCLUDE_DUMP
DllDummy,
#endif //INCLUDE_DUMP
#ifdef INCLUDE_QSORT
(DllFunc)qsort,
(DllFunc)bsearch,
#else //INCLUDE_QSORT
DllDummy,
DllDummy,
#endif //INCLUDE_QSORT
#ifdef INCLUDE_TIMELIB
(DllFunc)mktime,
(DllFunc)gmtime_r,
(DllFunc)gmtimeDst,
(DllFunc)gmtimeDstSet,
#else //INCLUDE_TIMELIB
DllDummy,
DllDummy,
DllDummy,
DllDummy,
#endif //INCLUDE_TIMELIB
(DllFunc)OS_AsmInterruptEnable,
(DllFunc)OS_HeapCreate,
(DllFunc)OS_HeapDestroy,
(DllFunc)OS_HeapMalloc,
(DllFunc)OS_HeapFree,
(DllFunc)OS_HeapAlternate,
(DllFunc)OS_HeapRegister,
(DllFunc)OS_ThreadCreate,
(DllFunc)OS_ThreadExit,
(DllFunc)OS_ThreadSelf,
(DllFunc)OS_ThreadSleep,
(DllFunc)OS_ThreadTime,
(DllFunc)OS_ThreadInfoSet,
(DllFunc)OS_ThreadInfoGet,
(DllFunc)OS_ThreadPriorityGet,
(DllFunc)OS_ThreadPrioritySet,
(DllFunc)OS_ThreadProcessId,
(DllFunc)OS_ThreadCpuLock,
(DllFunc)OS_SemaphoreCreate,
(DllFunc)OS_SemaphoreDelete,
(DllFunc)OS_SemaphorePend,
(DllFunc)OS_SemaphorePost,
(DllFunc)OS_MutexCreate,
(DllFunc)OS_MutexDelete,
(DllFunc)OS_MutexPend,
(DllFunc)OS_MutexPost,
(DllFunc)OS_MQueueCreate,
(DllFunc)OS_MQueueDelete,
(DllFunc)OS_MQueueSend,
(DllFunc)OS_MQueueGet,
(DllFunc)OS_Job,
(DllFunc)OS_TimerCreate,
(DllFunc)OS_TimerDelete,
(DllFunc)OS_TimerCallback,
(DllFunc)OS_TimerStart,
(DllFunc)OS_TimerStop,
(DllFunc)OS_InterruptRegister,
(DllFunc)OS_InterruptStatus,
(DllFunc)OS_InterruptMaskSet,
(DllFunc)OS_InterruptMaskClear,
(DllFunc)UartPrintf,
(DllFunc)UartPrintfPoll,
(DllFunc)UartPrintfCritical,
(DllFunc)UartScanf,
(DllFunc)puts,
(DllFunc)getch,
(DllFunc)kbhit,
(DllFunc)Led,
(DllFunc)FP_Sqrt,
(DllFunc)FP_Cos,
(DllFunc)FP_Sin,
(DllFunc)FP_Atan,
(DllFunc)FP_Atan2,
(DllFunc)FP_Exp,
(DllFunc)FP_Log,
(DllFunc)FP_Pow,
#ifdef INCLUDE_FILESYS
(DllFunc)OS_fopen,
(DllFunc)OS_fclose,
(DllFunc)OS_fread,
(DllFunc)OS_fwrite,
(DllFunc)OS_fseek,
(DllFunc)OS_fmkdir,
(DllFunc)OS_fdir,
(DllFunc)OS_fdelete,
#else //INCLUDE_FILESYS
DllDummy,
DllDummy,
DllDummy,
DllDummy,
DllDummy,
DllDummy,
DllDummy,
DllDummy,
#endif //INCLUDE_FILESYS
#ifndef WIN32
(DllFunc)FlashRead,
(DllFunc)FlashWrite,
(DllFunc)FlashErase,
#else //WIN32
DllDummy,
DllDummy,
DllDummy,
#endif //WIN32
(DllFunc)IPOpen,
(DllFunc)IPWriteFlush,
(DllFunc)IPWrite,
(DllFunc)IPRead,
(DllFunc)IPClose,
(DllFunc)IPPrintf,
(DllFunc)IPResolve,
(DllFunc)IPAddressSelf,
(DllFunc)IPNameValue
};
#endif //DLL_SETUP
// Included by DLL to call OS functions via array of function pointers
#if defined(DLL_CALL) || !defined(DLL_SETUP)
enum {
ENUM_strcpy,
ENUM_strncpy,
ENUM_strcat,
ENUM_strncat,
ENUM_strcmp,
ENUM_strncmp,
ENUM_strstr,
ENUM_strlen,
ENUM_memcpy,
ENUM_memmove,
ENUM_memcmp,
ENUM_memset,
ENUM_abs,
ENUM_rand,
ENUM_srand,
ENUM_strtol,
ENUM_atoi,
ENUM_itoa,
ENUM_sprintf,
ENUM_sscanf,
ENUM_dump,
ENUM_qsort,
ENUM_bsearch,
ENUM_mktime,
ENUM_gmtime_r,
ENUM_gmtimeDst,
ENUM_gmtimeDstSet,
ENUM_OS_AsmInterruptEnable,
ENUM_OS_HeapCreate,
ENUM_OS_HeapDestroy,
ENUM_OS_HeapMalloc,
ENUM_OS_HeapFree,
ENUM_OS_HeapAlternate,
ENUM_OS_HeapRegister,
ENUM_OS_ThreadCreate,
ENUM_OS_ThreadExit,
ENUM_OS_ThreadSelf,
ENUM_OS_ThreadSleep,
ENUM_OS_ThreadTime,
ENUM_OS_ThreadInfoSet,
ENUM_OS_ThreadInfoGet,
ENUM_OS_ThreadPriorityGet,
ENUM_OS_ThreadPrioritySet,
ENUM_OS_ThreadProcessId,
ENUM_OS_ThreadCpuLock,
ENUM_OS_SemaphoreCreate,
ENUM_OS_SemaphoreDelete,
ENUM_OS_SemaphorePend,
ENUM_OS_SemaphorePost,
ENUM_OS_MutexCreate,
ENUM_OS_MutexDelete,
ENUM_OS_MutexPend,
ENUM_OS_MutexPost,
ENUM_OS_MQueueCreate,
ENUM_OS_MQueueDelete,
ENUM_OS_MQueueSend,
ENUM_OS_MQueueGet,
ENUM_OS_Job,
ENUM_OS_TimerCreate,
ENUM_OS_TimerDelete,
ENUM_OS_TimerCallback,
ENUM_OS_TimerStart,
ENUM_OS_TimerStop,
ENUM_OS_InterruptRegister,
ENUM_OS_InterruptStatus,
ENUM_OS_InterruptMaskSet,
ENUM_OS_InterruptMaskClear,
ENUM_UartPrintf,
ENUM_UartPrintfPoll,
ENUM_UartPrintfCritical,
ENUM_UartScanf,
ENUM_puts,
ENUM_getch,
ENUM_kbhit,
ENUM_Led,
ENUM_FP_Sqrt,
ENUM_FP_Cos,
ENUM_FP_Sin,
ENUM_FP_Atan,
ENUM_FP_Atan2,
ENUM_FP_Exp,
ENUM_FP_Log,
ENUM_FP_Pow,
ENUM_OS_fopen,
ENUM_OS_fclose,
ENUM_OS_fread,
ENUM_OS_fwrite,
ENUM_OS_fseek,
ENUM_OS_fmkdir,
ENUM_OS_fdir,
ENUM_OS_fdelete,
ENUM_FlashRead,
ENUM_FlashWrite,
ENUM_FlashErase,
ENUM_IPOpen,
ENUM_IPWriteFlush,
ENUM_IPWrite,
ENUM_IPRead,
ENUM_IPClose,
ENUM_IPPrintf,
ENUM_IPResolve,
ENUM_IPAddressSelf,
ENUM_IPNameValue
};
extern const DllFunc *DllF;
#undef strcpy
#undef strcat
#undef strncat
#undef strcmp
#undef strlen
#undef memcpy
#undef memcmp
#undef memset
#undef abs
#undef atoi
#undef puts
#undef getch
#undef kbhit
#define strcpy DllF[ENUM_strcpy]
#define strncpy DllF[ENUM_strncpy]
#define strcat DllF[ENUM_strcat]
#define strncat DllF[ENUM_strncat]
#define strcmp (int)DllF[ENUM_strcmp]
#define strncmp (int)DllF[ENUM_strncmp]
#define strstr DllF[ENUM_strstr]
#define strlen (int)DllF[ENUM_strlen]
#define memcpy DllF[ENUM_memcpy]
#define memmove DllF[ENUM_memmove]
#define memcmp (int)DllF[ENUM_memcmp]
#define memset DllF[ENUM_memset]
#define abs (int)DllF[ENUM_abs]
#define rand (int)DllF[ENUM_rand]
#define srand DllF[ENUM_srand]
#define strtol (int)DllF[ENUM_strtol]
#define atoi (int)DllF[ENUM_atoi]
#define itoa DllF[ENUM_itoa]
#define sprintf DllF[ENUM_sprintf]
#define sscanf DllF[ENUM_sscanf]
#define dump DllF[ENUM_dump]
#define qsort DllF[ENUM_qsort]
#define bsearch DllF[ENUM_bsearch]
#define mktime DllF[ENUM_mktime]
#define gmtime_r DllF[ENUM_gmtime_r]
#define gmtimeDst DllF[ENUM_gmtimeDst]
#define gmtimeDstSet DllF[ENUM_gmtimeDstSet]
#define OS_AsmInterruptEnable (int)DllF[ENUM_OS_AsmInterruptEnable]
#define OS_HeapCreate DllF[ENUM_OS_HeapCreate]
#define OS_HeapDestroy DllF[ENUM_OS_HeapDestroy]
#define OS_HeapMalloc DllF[ENUM_OS_HeapMalloc]
#define OS_HeapFree DllF[ENUM_OS_HeapFree]
#define OS_HeapAlternate DllF[ENUM_OS_HeapAlternate]
#define OS_HeapRegister DllF[ENUM_OS_HeapRegister]
#define OS_ThreadCreate DllF[ENUM_OS_ThreadCreate]
#define OS_ThreadExit DllF[ENUM_OS_ThreadExit]
#define OS_ThreadSelf DllF[ENUM_OS_ThreadSelf]
#define OS_ThreadSleep DllF[ENUM_OS_ThreadSleep]
#define OS_ThreadTime DllF[ENUM_OS_ThreadTime]
#define OS_ThreadInfoSet DllF[ENUM_OS_ThreadInfoSet]
#define OS_ThreadInfoGet DllF[ENUM_OS_ThreadInfoGet]
#define OS_ThreadPriorityGet (int)DllF[ENUM_OS_ThreadPriorityGet]
#define OS_ThreadPrioritySet DllF[ENUM_OS_ThreadPrioritySet]
#define OS_ThreadProcessId DllF[ENUM_OS_ThreadProcessId]
#define OS_ThreadCpuLock DllF[ENUM_OS_ThreadCpuLock]
#define OS_SemaphoreCreate DllF[ENUM_OS_SemaphoreCreate]
#define OS_SemaphoreDelete DllF[ENUM_OS_SemaphoreDelete]
#define OS_SemaphorePend (int)DllF[ENUM_OS_SemaphorePend]
#define OS_SemaphorePost DllF[ENUM_OS_SemaphorePost]
#define OS_MutexCreate DllF[ENUM_OS_MutexCreate]
#define OS_MutexDelete DllF[ENUM_OS_MutexDelete]
#define OS_MutexPend (int)DllF[ENUM_OS_MutexPend]
#define OS_MutexPost DllF[ENUM_OS_MutexPost]
#define OS_MQueueCreate DllF[ENUM_OS_MQueueCreate]
#define OS_MQueueDelete DllF[ENUM_OS_MQueueDelete]
#define OS_MQueueSend DllF[ENUM_OS_MQueueSend]
#define OS_MQueueGet (int)DllF[ENUM_OS_MQueueGet]
#define OS_Job DllF[ENUM_OS_Job]
#define OS_TimerCreate DllF[ENUM_OS_TimerCreate]
#define OS_TimerDelete DllF[ENUM_OS_TimerDelete]
#define OS_TimerCallback DllF[ENUM_OS_TimerCallback]
#define OS_TimerStart DllF[ENUM_OS_TimerStart]
#define OS_TimerStop DllF[ENUM_OS_TimerStop]
#define OS_InterruptRegister DllF[ENUM_OS_InterruptRegister]
#define OS_InterruptStatus (int)DllF[ENUM_OS_InterruptStatus]
#define OS_InterruptMaskSet DllF[ENUM_OS_InterruptMaskSet]
#define OS_InterruptMaskClear DllF[ENUM_OS_InterruptMaskClear]
#define UartPrintf DllF[ENUM_UartPrintf]
#define UartPrintfPoll DllF[ENUM_UartPrintfPoll]
#define UartPrintfCritical DllF[ENUM_UartPrintfCritical]
#define UartScanf DllF[ENUM_UartScanf]
#define puts DllF[ENUM_puts]
#define getch (int)DllF[ENUM_getch]
#define kbhit (int)DllF[ENUM_kbhit]
#define Led DllF[ENUM_Led]
#define FP_Sqrt (float)(int)DllF[ENUM_FP_Sqrt]
#define FP_Cos (float)(int)DllF[ENUM_FP_Cos]
#define FP_Sin (float)(int)DllF[ENUM_FP_Sin]
#define FP_Atan (float)(int)DllF[ENUM_FP_Atan]
#define FP_Atan2 (float)(int)DllF[ENUM_FP_Atan2]
#define FP_Exp (float)(int)DllF[ENUM_FP_Exp]
#define FP_Log (float)(int)DllF[ENUM_FP_Log]
#define FP_Pow (float)(int)DllF[ENUM_FP_Pow]
#define OS_fopen DllF[ENUM_OS_fopen]
#define OS_fclose DllF[ENUM_OS_fclose]
#define OS_fread (int)DllF[ENUM_OS_fread]
#define OS_fwrite DllF[ENUM_OS_fwrite]
#define OS_fseek DllF[ENUM_OS_fseek]
#define OS_fmkdir DllF[ENUM_OS_fmkdir]
#define OS_fdir DllF[ENUM_OS_fdir]
#define OS_fdelete DllF[ENUM_OS_fdelete]
#define FlashRead DllF[ENUM_FlashRead]
#define FlashWrite DllF[ENUM_FlashWrite]
#define FlashErase DllF[ENUM_FlashErase]
#define IPOpen DllF[ENUM_IPOpen]
#define IPWriteFlush DllF[ENUM_IPWriteFlush]
#define IPWrite (int)DllF[ENUM_IPWrite]
#define IPRead (int)DllF[ENUM_IPRead]
#define IPClose DllF[ENUM_IPClose]
#define IPPrintf DllF[ENUM_IPPrintf]
#define IPResolve DllF[ENUM_IPResolve]
#define IPAddressSelf (int)DllF[ENUM_IPAddressSelf]
#define IPNameValue DllF[ENUM_IPNameValue]
#endif //DLL_CALL
#if defined(DLL_SETUP) && defined(DLL_CALL)
const DllFunc *DllF = DllFuncList;
#elif !defined(DLL_SETUP) && !defined(DLL_CALL) && !defined(DLL_ENTRY)
#define DLL_ENTRY 1
#endif //DLL_SETUP && DLL_CALL
// Included by DLL to initialize the DLL
#if defined(DLL_ENTRY) && !defined(NO_DLL_ENTRY)
const DllFunc *DllF; //array of function pointers
extern void *__bss_start;
extern void *_end;
void Start(IPSocket *socket, char *argv[]);
//Must be first function in file
void *__start(DllFunc *DllFuncList)
{
int *bss;
if(DllFuncList == NULL)
return (void*)__start; //address where DLL should be loaded
for(bss = (int*)&__bss_start; bss < (int*)&_end; ++bss)
*bss = 0;
DllF = DllFuncList;
return (void*)Start;
}
#endif //DLL_ENTRY
#ifdef DLL_STRINGS
const char * const DllStrings[] = {
"strcpy",
"strncpy",
"strcat",
"strncat",
"strcmp",
"strncmp",
"strstr",
"strlen",
"memcpy",
"memmove",
"memcmp",
"memset",
"abs",
"rand",
"srand",
"strtol",
"atoi",
"itoa",
"sprintf",
"sscanf",
"dump",
"qsort",
"bsearch",
"mktime",
"gmtime_r",
"gmtimeDst",
"gmtimeDstSet",
"OS_AsmInterruptEnable",
"OS_HeapCreate",
"OS_HeapDestroy",
"OS_HeapMalloc",
"OS_HeapFree",
"OS_HeapAlternate",
"OS_HeapRegister",
"OS_ThreadCreate",
"OS_ThreadExit",
"OS_ThreadSelf",
"OS_ThreadSleep",
"OS_ThreadTime",
"OS_ThreadInfoSet",
"OS_ThreadInfoGet",
"OS_ThreadPriorityGet",
"OS_ThreadPrioritySet",
"OS_ThreadProcessId",
"OS_ThreadCpuLock",
"OS_SemaphoreCreate",
"OS_SemaphoreDelete",
"OS_SemaphorePend",
"OS_SemaphorePost",
"OS_MutexCreate",
"OS_MutexDelete",
"OS_MutexPend",
"OS_MutexPost",
"OS_MQueueCreate",
"OS_MQueueDelete",
"OS_MQueueSend",
"OS_MQueueGet",
"OS_Job",
"OS_TimerCreate",
"OS_TimerDelete",
"OS_TimerCallback",
"OS_TimerStart",
"OS_TimerStop",
"OS_InterruptRegister",
"OS_InterruptStatus",
"OS_InterruptMaskSet",
"OS_InterruptMaskClear",
"printf", //"UartPrintf",
"UartPrintfPoll",
"UartPrintfCritical",
"scanf", //"UartScanf",
"puts",
"getch",
"kbhit",
"Led",
"FP_Sqrt",
"FP_Cos",
"FP_Sin",
"FP_Atan",
"FP_Atan2",
"FP_Exp",
"FP_Log",
"FP_Pow",
"OS_fopen",
"OS_fclose",
"OS_fread",
"OS_fwrite",
"OS_fseek",
"OS_fmkdir",
"OS_fdir",
"OS_fdelete",
"FlashRead",
"FlashWrite",
"FlashErase",
"IPOpen",
"IPWriteFlush",
"IPWrite",
"IPRead",
"IPClose",
"IPPrintf",
"IPResolve",
"IPAddressSelf",
"IPNameValue",
NULL
};
#endif //DLL_STRINGS
#endif //__DLL_H__

38
plasma/kernel/dlltest.c Normal file
View File

@@ -0,0 +1,38 @@
// dlltest.c
// Compile this program with "make dlltest".
// Then ftp test.bin to /flash/bin/dlltest.
// Then from a telnet prompt type "dlltest".
#include "dll.h"
void SocketReceive(IPSocket *socket)
{
}
void MyThread(void *sock)
{
char buf[80];
int i, bytes;
IPSocket *socket = sock;
for(i = 0; i < 10; ++i)
{
bytes = IPRead(socket, buf, sizeof(buf)-1);
buf[bytes] = 0;
IPPrintf(socket, "%d %s\n", i, buf);
OS_ThreadSleep(100);
}
socket->funcPtr = socket->userFunc; //restore socket receive function
}
// Function shouldn't block
void Start(IPSocket *socket, char *argv[])
{
IPPrintf(socket, "Hello from dlltest\n");
socket->userFunc = socket->funcPtr; //remember prev socket receive func
socket->funcPtr = SocketReceive; //new socket receive function
OS_ThreadCreate("MyThread", MyThread, socket, 100, 0);
}

408
plasma/kernel/ethernet.c Normal file
View File

@@ -0,0 +1,408 @@
/*--------------------------------------------------------------------
* TITLE: Plasma Ethernet MAC
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
* DATE CREATED: 1/12/08
* FILENAME: ethernet.c
* PROJECT: Plasma CPU core
* COPYRIGHT: Software placed into the public domain by the author.
* Software 'as is' without warranty. Author liable for nothing.
* DESCRIPTION:
* Ethernet MAC implementation.
* Data is received from the Ethernet PHY four bits at a time.
* After 32-bits are received they are written to 0x13ff0000 + N.
* The data is received LSB first for each byte which requires the
* nibbles to be swapped.
* Transmit data is read from 0x13fe0000. Write length/4+1 to
* ETHERNET_REG to start transfer.
*--------------------------------------------------------------------*/
#include "plasma.h"
#include "rtos.h"
#include "tcpip.h"
#define POLYNOMIAL 0x04C11DB7 //CRC bit 33 is truncated
#define TOPBIT (1<<31)
#define BYTE_EMPTY 0xde //Data copied into receive buffer
#define COUNT_EMPTY 16 //Count to decide there isn't data
#define INDEX_MASK 0xffff //Size of receive buffer
//void dump(const unsigned char *data, int length);
static unsigned char gDestMac[]={0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static unsigned int CrcTable[256];
static unsigned char reflect[256];
static unsigned char reflectNibble[256];
static OS_Semaphore_t *SemEthernet, *SemEthTransmit;
static int gIndex; //byte index into 0x13ff0000 receive buffer
static int gCheckedBefore;
static int gEmptyBefore;
//Read received data from 0x13ff0000. Data starts with 0x5d+MACaddress.
//Data is being received while processing the data. Therefore,
//all errors require waiting and then re-processing the data
//to see if the error is fixed by receiving the rest of the packet.
int EthernetReceive(unsigned char *buffer, int length)
{
int count;
int start, i, j, shift, offset;
int byte, byteNext;
unsigned long crc;
int byteCrc;
volatile unsigned char *buf = (unsigned char*)ETHERNET_RECEIVE;
int countEmpty, countEmptyGoal, countOk, needWait;
int packetExpected;
//Find the start of a frame
countEmpty = 0;
countOk = 0;
needWait = 0;
countEmptyGoal = COUNT_EMPTY;
packetExpected = MemoryRead(IRQ_STATUS) & IRQ_ETHERNET_RECEIVE;
if(packetExpected && buf[gIndex] == BYTE_EMPTY && gEmptyBefore)
{
//printf("Check ");
countEmptyGoal = 1500;
}
MemoryRead(ETHERNET_REG); //clear receive interrupt
for(i = 0; i < INDEX_MASK; ++i)
{
//Check if partial packet possibly received
if(needWait && gCheckedBefore == 0 && countOk != i && countEmpty != i)
{
gCheckedBefore = 1;
//printf("W(%d,%d,%d)", i, countOk, countEmpty);
return 0; //Wait for more data
}
//Detect start of frame
byte = buf[(gIndex + i) & INDEX_MASK];
if(byte == gDestMac[countOk] || (countOk && byte == 0xff))
{
if(++countOk == sizeof(gDestMac))
{
//Set bytes before 0x5d to BYTE_EMPTY
offset = i - (int)sizeof(gDestMac);
//if(offset > 3)
// printf("es%d ", offset);
for(j = 0; j <= offset; ++j)
{
buf[gIndex] = BYTE_EMPTY;
gIndex = (gIndex + 1) & INDEX_MASK;
}
break;
}
}
else
{
//if(countOk)
// printf("N%d ", countOk);
if(countOk == 3 && byte == BYTE_EMPTY)
needWait = 1;
if(byte == 0x5d)
countOk = 1;
else
countOk = 0;
}
//Check if remainder of buffer is empty
if(byte == BYTE_EMPTY)
{
if(++countEmpty >= countEmptyGoal)
{
//Set skiped bytes to BYTE_EMPTY
//if(i - countEmpty > 3)
//{
// printf("eb%d \n", i - countEmpty);
// //dump((char*)buf+gIndex, 0x200);
//}
for(j = 0; j <= i - countEmpty; ++j)
{
buf[gIndex] = BYTE_EMPTY;
gIndex = (gIndex + 1) & INDEX_MASK;
}
gCheckedBefore = 0;
if(countEmpty >= i && packetExpected)
gEmptyBefore = 1;
return 0;
}
}
else
{
if(countEmpty > 2 || (countEmpty > 0 && countEmpty == i))
needWait = 1;
countEmpty = 0;
gEmptyBefore = 0;
}
}
//Found start of frame. Now find end of frame and check CRC.
start = gIndex;
gIndex = (gIndex + 1) & INDEX_MASK; //skip 0x5d byte
crc = 0xffffffff;
for(count = 0; count < length; )
{
byte = buf[gIndex];
gIndex = (gIndex + 1) & INDEX_MASK;
byte = ((byte << 4) & 0xf0) | (byte >> 4); //swap nibbles
buffer[count++] = (unsigned char)byte;
byte = reflect[byte] ^ (crc >> 24); //calculate CRC32
crc = CrcTable[byte] ^ (crc << 8);
if(count >= 40)
{
//Check if CRC matches to detect end of frame
byteCrc = reflectNibble[crc >> 24];
byteNext = buf[gIndex];
if(byteCrc == byteNext)
{
for(i = 1; i < 4; ++i)
{
shift = 24 - (i << 3);
byteCrc = reflectNibble[(crc >> shift) & 0xff];
byteNext = buf[(gIndex + i) & 0xffff];
if(byteCrc != byteNext)
{
//printf("nope %d %d 0x%x 0x%x\n", count, i, byteCrc, byteNext);
i = 99;
}
}
if(i == 4)
{
//Found end of frame -- set used bytes to BYTE_EMPTY
//printf("Found it! %d\n", count);
gIndex = (gIndex + 4) & INDEX_MASK;
for(i = 0; i < count+5; ++i)
buf[(start + i) & INDEX_MASK] = BYTE_EMPTY;
while(gIndex & 3)
{
buf[gIndex] = BYTE_EMPTY;
gIndex = (gIndex + 1) & INDEX_MASK;
}
gCheckedBefore = 0;
return count;
}
}
}
}
gIndex = start;
if(gCheckedBefore)
{
//printf("CRC failure\n");
buf[gIndex] = BYTE_EMPTY;
}
gCheckedBefore = 1;
return 0; //wait for more data
}
//Copy transmit data to 0x13fe0000 with preamble and CRC32
void EthernetTransmit(unsigned char *buffer, int length)
{
int i, byte, shift;
unsigned long crc;
volatile unsigned char *buf = (unsigned char*)ETHERNET_TRANSMIT;
OS_SemaphorePend(SemEthTransmit, OS_WAIT_FOREVER);
//Wait for previous transfer to complete
for(i = 0; i < 10000; ++i)
{
if(MemoryRead(IRQ_STATUS) & IRQ_ETHERNET_TRANSMIT)
break;
}
//if(i > 100)
// printf("wait=%d ", i);
Led(2, 2);
while(length < 60 || (length & 3) != 0)
buffer[length++] = 0;
//Start of Ethernet frame
for(i = 0; i < 7; ++i)
buf[i] = 0x55;
buf[7] = 0x5d;
//Calculate CRC32
crc = 0xffffffff;
for(i = 0; i < length; ++i)
{
byte = buffer[i];
buf[i + 8] = (unsigned char)((byte << 4) | (byte >> 4)); //swap nibbles
byte = reflect[byte] ^ (crc >> 24); //calculate CRC32
crc = CrcTable[byte] ^ (crc << 8);
}
//Output CRC32
for(i = 0; i < 4; ++i)
{
shift = 24 - (i << 3);
byte = reflectNibble[(crc >> shift) & 0xff];
buf[length + 8 + i] = (unsigned char)byte;
}
//Start transfer
length = (length + 12 + 4) >> 2;
MemoryWrite(ETHERNET_REG, length);
Led(2, 0);
OS_SemaphorePost(SemEthTransmit);
}
void EthernetThread(void *arg)
{
int length;
int rc;
unsigned int ticks, ticksLast=0;
IPFrame *ethFrame=NULL;
(void)arg;
for(;;)
{
OS_InterruptMaskSet(IRQ_ETHERNET_RECEIVE);
OS_SemaphorePend(SemEthernet, 50); //wait for interrupt
//Process all received packets
for(;;)
{
if(ethFrame == NULL)
ethFrame = IPFrameGet(FRAME_COUNT_RCV);
if(ethFrame == NULL)
{
OS_ThreadSleep(50);
break;
}
length = EthernetReceive(ethFrame->packet, PACKET_SIZE);
if(length == 0)
break;
Led(1, 1);
rc = IPProcessEthernetPacket(ethFrame, length);
Led(1, 0);
if(rc)
ethFrame = NULL;
}
ticks = OS_ThreadTime();
if(ticks - ticksLast > 50)
{
IPTick();
ticksLast = ticks;
}
}
}
void EthernetIsr(void *arg)
{
(void)arg;
OS_InterruptMaskClear(IRQ_ETHERNET_TRANSMIT | IRQ_ETHERNET_RECEIVE);
OS_SemaphorePost(SemEthernet);
}
/******************* CRC32 calculations **********************
* The CRC32 code is modified from Michale Barr's article in
* Embedded Systems Programming January 2000.
* A CRC is really modulo-2 binary division. Substraction means XOR. */
static unsigned int Reflect(unsigned int value, int bits)
{
unsigned int num=0;
int i;
for(i = 0; i < bits; ++i)
{
num = (num << 1) | (value & 1);
value >>= 1;
}
return num;
}
static void CrcInit(void)
{
unsigned int remainder;
int dividend, bit, i;
//Compute the remainder of each possible dividend
for(dividend = 0; dividend < 256; ++dividend)
{
//Start with the dividend followed by zeros
remainder = dividend << 24;
//Perform modulo-2 division, a bit at a time
for(bit = 8; bit > 0; --bit)
{
//Try to divide the current data bit
if(remainder & TOPBIT)
remainder = (remainder << 1) ^ POLYNOMIAL;
else
remainder = remainder << 1;
}
CrcTable[dividend] = remainder;
}
for(i = 0; i < 256; ++i)
{
reflect[i] = (unsigned char)Reflect(i, 8);
reflectNibble[i] = (unsigned char)((Reflect((i >> 4) ^ 0xf, 4) << 4) |
Reflect(i ^ 0xf, 4));
}
}
static void SpinWait(int clocks)
{
int value = *(volatile int*)COUNTER_REG + clocks;
while(*(volatile int*)COUNTER_REG - value < 0)
;
}
void EthernetInit(unsigned char MacAddress[6])
{
//Format of SMI data: 0101 A4:A0 R4:R0 00 D15:D0
unsigned long data=0x5f800100; //SMI R0 = 10Mbps full duplex
//unsigned long data=0x5f800000; //SMI R0 = 10Mbps half duplex
int i, value;
volatile unsigned char *buf = (unsigned char*)ETHERNET_RECEIVE;
CrcInit();
for(i = 0; i < 6; ++i)
{
value = MacAddress[i];
gDestMac[i+1] = (unsigned char)((value >> 4) | (value << 4));
}
//Configure Ethernet PHY for 10Mbps full duplex via SMI interface
MemoryWrite(GPIO0_OUT, ETHERNET_MDIO | ETHERNET_MDIO_WE | ETHERENT_MDC);
for(i = 0; i < 34; ++i)
{
MemoryWrite(GPIO0_OUT, ETHERENT_MDC); //clock high
SpinWait(10);
MemoryWrite(GPIO0_CLEAR, ETHERENT_MDC); //clock low
SpinWait(10);
}
for(i = 31; i >= 0; --i)
{
value = (data >> i) & 1;
if(value)
MemoryWrite(GPIO0_OUT, ETHERNET_MDIO);
else
MemoryWrite(GPIO0_CLEAR, ETHERNET_MDIO);
MemoryWrite(GPIO0_OUT, ETHERENT_MDC); //clock high
SpinWait(10);
MemoryWrite(GPIO0_CLEAR, ETHERENT_MDC); //clock low
SpinWait(10);
}
MemoryWrite(GPIO0_CLEAR, ETHERNET_MDIO_WE | ETHERNET_ENABLE);
//Clear receive buffer
for(i = 0; i <= INDEX_MASK; ++i)
buf[i] = BYTE_EMPTY;
//Start receive DMA
MemoryWrite(GPIO0_OUT, ETHERNET_ENABLE);
//Setup interrupts for receiving data
SemEthernet = OS_SemaphoreCreate("eth", 0);
SemEthTransmit = OS_SemaphoreCreate("ethT", 1);
OS_ThreadCreate("eth", EthernetThread, NULL, 240, 0);
OS_InterruptRegister(IRQ_ETHERNET_RECEIVE, EthernetIsr);
}

767
plasma/kernel/filesys.c Normal file
View File

@@ -0,0 +1,767 @@
/*--------------------------------------------------------------------
* TITLE: Plasma File System
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
* DATE CREATED: 4/26/07
* FILENAME: filesys.c
* PROJECT: Plasma CPU core
* COPYRIGHT: Software placed into the public domain by the author.
* Software 'as is' without warranty. Author liable for nothing.
* DESCRIPTION:
* Plasma File System. Supports RAM, flash, and disk file systems.
* Possible call tree:
* OS_fclose()
* FileFindRecursive() //find the existing file
* FileOpen() //open root file system
* FileFind() //find the next level of directory
* OS_fread() //read the directory file
* BlockRead() //read blocks of directory
* MediaBlockRead() //low level read
* FileOpen() //open next directory
* OS_fwrite() //write file entry into directory
* BlockRead() //flush changes to directory
*--------------------------------------------------------------------*/
#ifdef WIN32
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define _LIBC
#endif
#include "rtos.h"
#define FLASH_SIZE 1024*1024*16
#define FLASH_SECTOR_SIZE 1024*128
#define FLASH_BLOCK_SIZE 512
#define FLASH_LN2_SIZE 9 //2^FLASH_LN2_SIZE == FLASH_BLOCK_SIZE
#define FLASH_OFFSET FLASH_SECTOR_SIZE //offset to start of flash file system
#define BLOCK_SIZE 512
#define FILE_NAME_SIZE 40
#define FULL_NAME_SIZE 128
#define BLOCK_MALLOC 0x0
#define BLOCK_EOF 0xffffffff
typedef enum {
FILE_MEDIA_RAM,
FILE_MEDIA_FLASH,
FILE_MEDIA_DISK
} OS_MediaType_e;
typedef struct OS_FileEntry_s {
char name[FILE_NAME_SIZE];
uint32 blockIndex; //first block of file
uint32 modifiedTime;
uint32 length;
uint8 isDirectory;
uint8 attributes;
uint8 valid;
uint8 mediaType;
uint16 blockSize; //Normally BLOCK_SIZE
} OS_FileEntry_t;
typedef struct OS_Block_s {
uint32 next;
uint8 data[4];
} OS_Block_t;
struct OS_FILE_s {
OS_FileEntry_t fileEntry; //written to directory upon OS_fclose()
uint8 fileModified;
uint8 blockModified;
uint32 blockIndex; //index of block
uint32 blockOffset; //byte offset into block
uint32 fileOffset; //byte offset into file
char fullname[FULL_NAME_SIZE]; //includes full path
OS_Block_t *block;
OS_Block_t *blockLocal; //local copy for flash or disk file system
};
static OS_FileEntry_t rootFileEntry;
static OS_Mutex_t *mutexFilesys;
// Public prototypes
#ifndef _FILESYS_
typedef struct OS_FILE_s OS_FILE;
#endif
OS_FILE *OS_fopen(char *name, char *mode);
void OS_fclose(OS_FILE *file);
int OS_fread(void *buffer, int size, int count, OS_FILE *file);
int OS_fwrite(void *buffer, int size, int count, OS_FILE *file);
int OS_fseek(OS_FILE *file, int offset, int mode);
int OS_fmkdir(char *name);
int OS_fdir(OS_FILE *dir, char name[64]);
void OS_fdelete(char *name);
/***************** Media Functions Start ***********************/
#ifdef INCLUDE_FLASH
#define FLASH_BLOCKS FLASH_SIZE/FLASH_BLOCK_SIZE
#define FLASH_START (FLASH_OFFSET+FLASH_BLOCKS/8*2)/FLASH_BLOCK_SIZE
static unsigned char FlashBlockEmpty[FLASH_BLOCKS/8];
static unsigned char FlashBlockUsed[FLASH_BLOCKS/8];
static int FlashBlock;
//Free unused flash blocks
static int MediaBlockCleanup(void)
{
int i, sector, block, count=0;
unsigned char *buf;
printf("FlashCleanup\n");
buf = (unsigned char*)malloc(FLASH_SECTOR_SIZE);
if(buf == NULL)
return 0;
for(sector = FLASH_OFFSET / FLASH_SECTOR_SIZE; sector < FLASH_SIZE / FLASH_SECTOR_SIZE; ++sector)
{
FlashRead((uint16*)buf, FLASH_SECTOR_SIZE*sector, FLASH_SECTOR_SIZE);
if(sector == FLASH_OFFSET / FLASH_SECTOR_SIZE)
{
for(i = 0; i < FLASH_BLOCKS/8; ++i)
FlashBlockEmpty[i] |= ~FlashBlockUsed[i];
memcpy(buf, FlashBlockEmpty, sizeof(FlashBlockEmpty));
memset(FlashBlockUsed, 0xff, sizeof(FlashBlockUsed));
memset(buf+sizeof(FlashBlockEmpty), 0xff, sizeof(FlashBlockUsed));
}
//Erase empty blocks
for(block = 0; block < FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE; ++block)
{
i = sector * FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE + block;
if(i < FLASH_BLOCKS/8 && (FlashBlockEmpty[i >> 3] & (1 << (i & 7))))
{
memset(buf + FLASH_BLOCK_SIZE*block, 0xff, FLASH_BLOCK_SIZE);
++count;
}
}
FlashErase(FLASH_SECTOR_SIZE * sector);
FlashWrite((uint16*)buf, FLASH_SECTOR_SIZE * sector, FLASH_SECTOR_SIZE);
}
free(buf);
return count;
}
int MediaBlockInit(void)
{
FlashRead((uint16*)FlashBlockEmpty, FLASH_OFFSET, sizeof(FlashBlockEmpty));
FlashRead((uint16*)FlashBlockUsed, FLASH_OFFSET+sizeof(FlashBlockEmpty),
sizeof(FlashBlockUsed));
FlashBlock = FLASH_START;
return FlashBlockEmpty[FlashBlock >> 3] & (1 << (FlashBlock & 7));
}
#endif
static uint32 MediaBlockMalloc(OS_FILE *file)
{
int i, j;
(void)i; (void)j;
if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
return (uint32)malloc(file->fileEntry.blockSize);
#ifdef INCLUDE_FLASH
//Find empty flash block
for(i = FlashBlock; i < FLASH_BLOCKS; ++i)
{
if(FlashBlockEmpty[i >> 3] & (1 << (i & 7)))
{
FlashBlock = i + 1;
FlashBlockEmpty[i >> 3] &= ~(1 << (i & 7));
j = i >> 3;
j &= ~1;
FlashWrite((uint16*)(FlashBlockEmpty + j), FLASH_OFFSET + j, 2);
return i;
}
}
i = MediaBlockCleanup();
if(i == 0)
return 0;
FlashBlock = FLASH_START;
return MediaBlockMalloc(file);
#else
return 0;
#endif
}
static void MediaBlockFree(OS_FILE *file, uint32 blockIndex)
{
if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
free((void*)blockIndex);
#ifdef INCLUDE_FLASH
else
{
int i=blockIndex, j;
FlashBlockUsed[i >> 3] &= ~(1 << (i & 7));
j = i >> 3;
j &= ~1;
FlashWrite((uint16*)(FlashBlockUsed + j), FLASH_OFFSET + sizeof(FlashBlockEmpty) + j, 2);
}
#endif
}
static void MediaBlockRead(OS_FILE *file, uint32 blockIndex)
{
if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
file->block = (OS_Block_t*)blockIndex;
#ifdef INCLUDE_FLASH
else
{
if(file->blockLocal == NULL)
file->blockLocal = (OS_Block_t*)malloc(FLASH_BLOCK_SIZE);
file->block = file->blockLocal;
FlashRead((uint16*)file->block, blockIndex << FLASH_LN2_SIZE, FLASH_BLOCK_SIZE);
}
#endif
}
static void MediaBlockWrite(OS_FILE *file, uint32 blockIndex)
{
(void)file;
(void)blockIndex;
#ifdef INCLUDE_FLASH
if(file->fileEntry.mediaType != FILE_MEDIA_RAM)
FlashWrite((uint16*)file->block, blockIndex << FLASH_LN2_SIZE, FLASH_BLOCK_SIZE);
#endif
}
/***************** Media Functions End *************************/
// Get the next block and write the old block if it was modified
static void BlockRead(OS_FILE *file, uint32 blockIndex)
{
uint32 blockIndexSave = blockIndex;
OS_MutexPend(mutexFilesys);
if(blockIndex == BLOCK_MALLOC)
{
// Get a new block
blockIndex = MediaBlockMalloc(file);
if(blockIndex == 0)
blockIndex = BLOCK_EOF;
if(file->block)
{
// Set next pointer in previous block
file->block->next = blockIndex;
file->blockModified = 1;
}
}
if(file->block && file->blockModified)
{
// Write block back to flash or disk
MediaBlockWrite(file, file->blockIndex);
file->blockModified = 0;
}
if(blockIndex == BLOCK_EOF)
{
OS_MutexPost(mutexFilesys);
return;
}
file->blockIndex = blockIndex;
file->blockOffset = 0;
MediaBlockRead(file, blockIndex);
if(blockIndexSave == BLOCK_MALLOC)
{
memset(file->block, 0xff, file->fileEntry.blockSize);
file->blockModified = 1;
}
OS_MutexPost(mutexFilesys);
}
int OS_fread(void *buffer, int size, int count, OS_FILE *file)
{
int items, bytes;
uint8 *buf = (uint8*)buffer;
for(items = 0; items < count; ++items)
{
for(bytes = 0; bytes < size; ++bytes)
{
if(file->fileOffset >= file->fileEntry.length &&
file->fileEntry.isDirectory == 0)
return items;
if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32))
{
if(file->block->next == BLOCK_EOF)
return items;
BlockRead(file, file->block->next);
}
*buf++ = file->block->data[file->blockOffset++];
++file->fileOffset;
}
}
return items;
}
int OS_fwrite(void *buffer, int size, int count, OS_FILE *file)
{
int items, bytes;
uint8 *buf = (uint8*)buffer;
OS_MutexPend(mutexFilesys);
file->blockModified = 1;
for(items = 0; items < count; ++items)
{
for(bytes = 0; bytes < size; ++bytes)
{
if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32))
{
if(file->block->next == BLOCK_EOF)
file->block->next = BLOCK_MALLOC;
BlockRead(file, file->block->next);
if(file->blockIndex == BLOCK_EOF)
{
count = 0;
--items;
break;
}
file->blockModified = 1;
}
file->block->data[file->blockOffset++] = *buf++;
++file->fileOffset;
}
}
file->blockModified = 1;
file->fileModified = 1;
if(file->fileOffset > file->fileEntry.length)
file->fileEntry.length = file->fileOffset;
OS_MutexPost(mutexFilesys);
return items;
}
int OS_fseek(OS_FILE *file, int offset, int mode)
{
if(mode == 1) //SEEK_CUR
offset += file->fileOffset;
else if(mode == 2) //SEEK_END
offset += file->fileEntry.length;
file->fileOffset = offset;
BlockRead(file, file->fileEntry.blockIndex);
while(offset > (int)file->fileEntry.blockSize - (int)sizeof(uint32))
{
BlockRead(file, file->block->next);
offset -= file->fileEntry.blockSize - (int)sizeof(uint32);
}
file->blockOffset = offset;
return 0;
}
static int FileOpen(OS_FILE *file, char *name, OS_FileEntry_t *fileEntry)
{
memset(file, 0, sizeof(OS_FILE));
if(fileEntry == NULL)
{
// Open root file
memcpy(&file->fileEntry, &rootFileEntry, sizeof(OS_FileEntry_t));
}
else if(fileEntry->valid == 1)
{
// Open existing file
memcpy(&file->fileEntry, fileEntry, sizeof(OS_FileEntry_t));
}
else
{
// Initialize new file
file->fileModified = 1;
file->blockModified = 1;
memset(&file->fileEntry, 0, sizeof(OS_FileEntry_t));
file->fileEntry.isDirectory = 0;
file->fileEntry.length = 0;
strncpy(file->fileEntry.name, name, FILE_NAME_SIZE-1);
file->fileEntry.blockIndex = 0;
file->fileEntry.valid = 1;
file->fileEntry.blockSize = fileEntry->blockSize;
file->fileEntry.mediaType = fileEntry->mediaType;
}
BlockRead(file, file->fileEntry.blockIndex); //Get first block
file->fileEntry.blockIndex = file->blockIndex;
file->fileOffset = 0;
if(file->blockIndex == BLOCK_EOF)
return -1;
return 0;
}
static int FileFind(OS_FILE *directory, char *name, OS_FileEntry_t *fileEntry)
{
int count, rc = -1;
uint32 blockIndex, blockOffset;
uint32 blockIndexEmpty=BLOCK_EOF, blockOffsetEmpty=0;
// Loop through files in directory
for(;;)
{
blockIndex = directory->blockIndex;
blockOffset = directory->blockOffset;
count = OS_fread(fileEntry, sizeof(OS_FileEntry_t), 1, directory);
if(count == 0 || fileEntry->blockIndex == BLOCK_EOF)
break;
if(fileEntry->valid == 1 && strcmp(fileEntry->name, name) == 0)
{
rc = 0; //Found the file in the directory
break;
}
if(fileEntry->valid != 1 && blockIndexEmpty == BLOCK_EOF)
{
blockIndexEmpty = blockIndex;
blockOffsetEmpty = blockOffset;
}
}
if(rc == 0 || directory->fileEntry.mediaType == FILE_MEDIA_FLASH ||
blockIndexEmpty == BLOCK_EOF)
{
// Backup to start of fileEntry or last entry in directory
if(directory->blockIndex != blockIndex)
BlockRead(directory, blockIndex);
directory->blockOffset = blockOffset;
}
else
{
// Backup to empty slot
if(directory->blockIndex != blockIndexEmpty)
BlockRead(directory, blockIndexEmpty);
directory->blockOffset = blockOffsetEmpty;
}
return rc;
}
static int FileFindRecursive(OS_FILE *directory, char *name,
OS_FileEntry_t *fileEntry, char *filename)
{
int rc, length;
rc = FileOpen(directory, NULL, NULL); //Open root directory
for(;;)
{
if(name[0] == '/')
++name;
for(length = 0; length < FILE_NAME_SIZE; ++length)
{
if(name[length] == 0 || name[length] == '/')
break;
filename[length] = name[length];
}
filename[length] = 0;
rc = FileFind(directory, filename, fileEntry); //Find file
if(rc)
{
// File not found
fileEntry->mediaType = directory->fileEntry.mediaType;
fileEntry->blockSize = directory->fileEntry.blockSize;
fileEntry->valid = 0;
if(strstr(name, "/") == NULL)
return rc;
else
return -2; //can't find parent directory
}
name += length;
if(name[0])
rc = FileOpen(directory, filename, fileEntry); //Open subdir
else
break;
}
return rc;
}
OS_FILE *OS_fopen(char *name, char *mode)
{
OS_FILE *file;
OS_FileEntry_t fileEntry;
OS_FILE dir;
char filename[FILE_NAME_SIZE]; //Name without directories
int rc;
if(rootFileEntry.blockIndex == 0)
{
// Mount file system
mutexFilesys = OS_MutexCreate("filesys");
memset(&dir, 0, sizeof(OS_FILE));
dir.fileEntry.blockSize = BLOCK_SIZE;
//dir.fileEntry.mediaType = FILE_MEDIA_FLASH; //Test flash
BlockRead(&dir, BLOCK_MALLOC);
strcpy(rootFileEntry.name, "/");
rootFileEntry.mediaType = dir.fileEntry.mediaType;
rootFileEntry.blockIndex = dir.blockIndex;
rootFileEntry.blockSize = dir.fileEntry.blockSize;
rootFileEntry.isDirectory = 1;
BlockRead(&dir, BLOCK_EOF); //Flush data
#ifdef INCLUDE_FLASH
file = OS_fopen("flash", "w+");
if(file == NULL)
return NULL;
file->fileEntry.isDirectory = 1;
file->fileEntry.mediaType = FILE_MEDIA_FLASH;
file->fileEntry.blockSize = FLASH_BLOCK_SIZE;
file->blockLocal = file->block;
file->block = NULL;
rc = MediaBlockInit();
if(rc == 1)
BlockRead(file, BLOCK_MALLOC);
else
BlockRead(file, FLASH_START);
file->fileEntry.blockIndex = file->blockIndex;
OS_fclose(file);
#endif
}
file = (OS_FILE*)malloc(sizeof(OS_FILE));
if(file == NULL)
return NULL;
OS_MutexPend(mutexFilesys);
if(name[0] == 0 || strcmp(name, "/") == 0)
{
FileOpen(file, NULL, NULL);
OS_MutexPost(mutexFilesys);
return file;
}
if(mode[0] == 'w')
{
//Don't over write a directory
fileEntry.isDirectory = 0;
rc = FileFindRecursive(&dir, name, &fileEntry, filename);
if(dir.blockLocal)
free(dir.blockLocal);
if(rc == 0)
{
if(fileEntry.isDirectory)
{
free(file);
return NULL;
}
OS_fdelete(name);
}
}
rc = FileFindRecursive(&dir, name, &fileEntry, filename);
if(dir.blockLocal)
free(dir.blockLocal);
if(rc == -2 || (rc && mode[0] == 'r'))
{
free(file);
OS_MutexPost(mutexFilesys);
return NULL;
}
if(rc)
fileEntry.valid = 0;
rc = FileOpen(file, filename, &fileEntry); //Open file
file->fullname[0] = 0;
strncat(file->fullname, name, FULL_NAME_SIZE);
OS_MutexPost(mutexFilesys);
if(mode[0] == 'a')
OS_fseek(file, 0, 2); //goto end of file
return file;
}
void OS_fclose(OS_FILE *file)
{
OS_FileEntry_t fileEntry;
OS_FILE dir;
char filename[FILE_NAME_SIZE];
int rc;
if(file->fileModified)
{
// Write file->fileEntry into parent directory
OS_MutexPend(mutexFilesys);
BlockRead(file, BLOCK_EOF);
rc = FileFindRecursive(&dir, file->fullname, &fileEntry, filename);
if(file->fileEntry.mediaType == FILE_MEDIA_FLASH && rc == 0)
{
// Invalidate old entry and add new entry at the end
fileEntry.valid = 0;
OS_fwrite(&fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
FileFind(&dir, "endoffile", &fileEntry);
}
OS_fwrite(&file->fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
BlockRead(&dir, BLOCK_EOF); //flush data
if(dir.blockLocal)
free(dir.blockLocal);
OS_MutexPost(mutexFilesys);
}
if(file->blockLocal)
free(file->blockLocal);
free(file);
}
int OS_fmkdir(char *name)
{
OS_FILE *file;
file = OS_fopen(name, "w+");
if(file == NULL)
return -1;
file->fileEntry.isDirectory = 1;
OS_fclose(file);
return 0;
}
void OS_fdelete(char *name)
{
OS_FILE dir, file;
OS_FileEntry_t fileEntry;
int rc;
uint32 blockIndex;
char filename[FILE_NAME_SIZE]; //Name without directories
OS_MutexPend(mutexFilesys);
rc = FileFindRecursive(&dir, name, &fileEntry, filename);
if(rc == 0)
{
FileOpen(&file, NULL, &fileEntry);
for(blockIndex = file.blockIndex; file.block->next != BLOCK_EOF; blockIndex = file.blockIndex)
{
BlockRead(&file, file.block->next);
MediaBlockFree(&file, blockIndex);
}
MediaBlockFree(&file, blockIndex);
fileEntry.valid = 0;
OS_fwrite((char*)&fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
BlockRead(&dir, BLOCK_EOF);
if(file.blockLocal)
free(file.blockLocal);
}
if(dir.blockLocal)
free(dir.blockLocal);
OS_MutexPost(mutexFilesys);
}
int OS_flength(char *entry)
{
OS_FileEntry_t *entry2=(OS_FileEntry_t*)entry;
return entry2->length;
}
int OS_fdir(OS_FILE *dir, char name[64])
{
OS_FileEntry_t *fileEntry = (OS_FileEntry_t*)name;
int count;
for(;;)
{
count = OS_fread(fileEntry, sizeof(OS_FileEntry_t), 1, dir);
if(count == 0 || fileEntry->blockIndex == BLOCK_EOF)
return -1;
if(fileEntry->valid == 1)
break;
}
return 0;
}
/*************************************************/
#define TEST_FILES
#ifdef TEST_FILES
int DirRecursive(char *name)
{
OS_FileEntry_t fileEntry;
OS_FILE *dir;
char fullname[FULL_NAME_SIZE];
int rc;
dir = OS_fopen(name, "r");
for(;;)
{
rc = OS_fdir(dir, (char*)&fileEntry);
if(rc)
break;
printf("%s %d\n", fileEntry.name, fileEntry.length);
if(fileEntry.isDirectory)
{
if(strcmp(name, "/") == 0)
sprintf(fullname, "/%s", fileEntry.name);
else
sprintf(fullname, "%s/%s", name, fileEntry.name);
DirRecursive(fullname);
}
}
OS_fclose(dir);
return 0;
}
int OS_ftest(void)
{
OS_FILE *file;
char *buf;
int count;
int i, j;
buf = (char*)malloc(5000);
memset(buf, 0, 5000);
for(count = 0; count < 4000; ++count)
buf[count] = (char)('A' + (count % 26));
OS_fmkdir("dir");
OS_fmkdir("/dir/subdir");
file = OS_fopen("/dir/subdir/test.txt", "w");
count = OS_fwrite(buf, 1, 4000, file);
OS_fclose(file);
memset(buf, 0, 5000);
file = OS_fopen("/dir/subdir/test.txt", "r");
count = OS_fread(buf, 1, 5000, file);
OS_fclose(file);
printf("(%s)\n", buf);
DirRecursive("/");
for(i = 0; i < 5; ++i)
{
sprintf(buf, "/dir%d", i);
OS_fmkdir(buf);
for(j = 0; j < 5; ++j)
{
sprintf(buf, "/dir%d/file%d%d", i, i, j);
file = OS_fopen(buf, "w");
sprintf(buf, "i=%d j=%d", i, j);
OS_fwrite(buf, 1, 8, file);
OS_fclose(file);
}
}
OS_fdelete("/dir1/file12");
DirRecursive("/");
file = OS_fopen("/baddir/myfile.txt", "w");
if(file)
printf("ERROR!\n");
for(i = 0; i < 5; ++i)
{
for(j = 0; j < 5; ++j)
{
sprintf(buf, "/dir%d/file%d%d", i, i, j);
file = OS_fopen(buf, "r");
if(file)
{
count = OS_fread(buf, 1, 500, file);
printf("i=%d j=%d count=%d (%s)\n", i, j, count, buf);
OS_fclose(file);
}
}
}
OS_fdelete("/dir/subdir/test.txt");
OS_fdelete("/dir/subdir");
OS_fdelete("/dir");
for(i = 0; i < 5; ++i)
{
for(j = 0; j < 5; ++j)
{
sprintf(buf, "/dir%d/file%d%d", i, i, j);
OS_fdelete(buf);
}
sprintf(buf, "/dir%d", i);
OS_fdelete(buf);
}
DirRecursive("/");
free(buf);
return 0;
}
#endif //TEST_FILES

52
plasma/kernel/flash.c Normal file
View File

@@ -0,0 +1,52 @@
/*--------------------------------------------------------------------
* TITLE: Plasma Flash
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
* DATE CREATED: 12/17/05
* FILENAME: plasma.h
* PROJECT: Plasma CPU core
* COPYRIGHT: Software placed into the public domain by the author.
* Software 'as is' without warranty. Author liable for nothing.
* DESCRIPTION:
* Plasma flash controller
* Only the lower 16-bits of each 32-bit word are connected --
* this changes the address mapping to the flash.
* ByteOffset and bytes must be a multiple of two.
*--------------------------------------------------------------------*/
#include "plasma.h"
#include "rtos.h"
void FlashRead(uint16 *dst, uint32 byteOffset, int bytes)
{
volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
*ptr = 0xff; //read mode
while(bytes > 0)
{
*dst++ = (uint16)*ptr++;
bytes -= 2;
}
}
void FlashWrite(uint16 *src, uint32 byteOffset, int bytes)
{
volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
while(bytes > 0)
{
*ptr = 0x40; //write mode
*ptr++ = *src++; //write data
while((*ptr & 0x80) == 0) //check status
;
bytes -= 2;
}
}
void FlashErase(uint32 byteOffset)
{
volatile uint32 *ptr=(uint32*)(FLASH_BASE + (byteOffset << 1));
*ptr = 0x20; //erase block
*ptr = 0xd0; //confirm
while((*ptr & 0x80) == 0) //check status
;
}

230
plasma/kernel/http.c Normal file
View File

@@ -0,0 +1,230 @@
/*--------------------------------------------------------------------
* TITLE: Plasma TCP/IP HTTP Server
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
* DATE CREATED: 4/22/06
* FILENAME: http.c
* PROJECT: Plasma CPU core
* COPYRIGHT: Software placed into the public domain by the author.
* Software 'as is' without warranty. Author liable for nothing.
* DESCRIPTION:
* Plasma TCP/IP HTTP Server
*--------------------------------------------------------------------*/
#ifdef WIN32
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define _LIBC
#endif
#include "rtos.h"
#include "tcpip.h"
#ifdef WIN32
#define UartPrintf printf
#define OS_MQueueCreate(A,B,C) 0
#define OS_MQueueGet(A,B,C) 0
#define OS_ThreadCreate(A,B,C,D,E) 0
#endif
static const char pageGif[]=
{
"HTTP/1.0 200 OK\r\n"
"Content-Length: %d\r\n"
"Content-Type: binary/gif\r\n\r\n"
};
static const char pageGif2[]=
{
"HTTP/1.0 200 OK\r\n"
"Content-Type: binary/gif\r\n\r\n"
};
static const char pageBinary[]=
{
"HTTP/1.0 200 OK\r\n"
"Content-Length: %d\r\n"
"Content-Type: binary/binary\r\n\r\n"
};
static const char pageBinary2[]=
{
"HTTP/1.0 200 OK\r\n"
"Content-Type: binary/binary\r\n\r\n"
};
static const char pageHtml[]={
"HTTP/1.0 200 OK\r\n"
"Content-Length: %d\r\n"
"Content-Type: text/html\r\n\r\n"
};
static const char pageHtml2[]={
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n\r\n"
};
static const char pageText[]={
"HTTP/1.0 200 OK\r\n"
"Content-Length: %d\r\n"
"Content-Type: text/text\r\n\r\n"
};
static const char pageEmpty[]=
{
"HTTP/1.0 404 OK\r\n"
"Content-Length: 0\r\n"
"Content-Type: text/html\r\n\r\n"
};
static const PageEntry_t *HtmlPages;
static int HtmlFiles;
void HttpServer(IPSocket *socket)
{
uint8 buf[600];
char filename[80];
int bytes, i, length, len, needFooter;
char *name=NULL, *page=NULL;
const char *header, *header2;
if(socket == NULL)
return;
if(socket->funcPtr != HttpServer && socket->funcPtr)
{
socket->funcPtr(socket);
return;
}
bytes = IPRead(socket, buf, sizeof(buf)-1);
if(bytes)
{
buf[bytes] = 0;
if(strncmp((char*)buf, "GET /", 5) == 0)
{
for(i = 0; ; ++i)
{
length = HtmlPages[i].length;
if(length == -1)
break;
name = (char*)HtmlPages[i].name;
page = (char*)HtmlPages[i].page;
len = (int)strlen(name);
if(strncmp((char*)buf+4, name, len) == 0)
break;
}
#if defined(WIN32) || defined(INCLUDE_FILESYS)
if(length == HTML_LENGTH_LIST_END && HtmlFiles)
{
FILE *file;
char *ptr;
name = (char*)buf + 5;
ptr = strstr(name, " ");
if(ptr)
*ptr = 0;
strcpy(filename, "/web/");
strncat(filename, name, 60);
file = fopen(filename, "rb");
if(file == NULL)
{
strcpy(filename, "/flash/web/");
strncat(filename, name, 60);
file = fopen(filename, "rb");
}
if(file)
{
if(strstr(name, ".htm"))
IPWrite(socket, (uint8*)pageHtml2, sizeof(pageHtml2)-1);
else if(strstr(name, ".gif"))
IPWrite(socket, (uint8*)pageGif2, sizeof(pageGif2)-1);
else
IPWrite(socket, (uint8*)pageBinary2, sizeof(pageBinary2)-1);
for(;;)
{
len = fread(buf, 1, sizeof(buf), file);
if(len == 0)
break;
IPWrite(socket, (uint8*)buf, len);
}
fclose(file);
IPWriteFlush(socket);
IPClose(socket);
return;
}
}
#endif
if(length != HTML_LENGTH_LIST_END)
{
if(length == HTML_LENGTH_CALLBACK)
{
IPFuncPtr funcPtr = (IPFuncPtr)(uint32)page;
funcPtr(socket, buf, bytes);
return;
}
if(length == 0)
length = (int)strlen(page);
needFooter = 0;
header2 = NULL;
if(strstr(name, ".html"))
header = pageHtml;
else if(strstr(name, ".htm") || strcmp(name, "/ ") == 0)
{
header = pageHtml;
header2 = HtmlPages[0].page;
needFooter = 1;
}
else if(strstr(HtmlPages[i].name, ".gif"))
header = pageGif;
else
header = pageBinary;
len = 0;
if(header2)
len += (int)strlen(header2) + (int)strlen(HtmlPages[1].page);
sprintf((char*)buf, header, length + len);
IPWrite(socket, buf, (int)strlen((char*)buf));
if(header2)
IPWrite(socket, (uint8*)header2, (int)strlen(header2));
IPWrite(socket, (uint8*)page, length);
if(needFooter)
IPWrite(socket, (uint8*)HtmlPages[1].page, (int)strlen(HtmlPages[1].page));
}
else
{
IPWrite(socket, (uint8*)pageEmpty, (int)strlen(pageEmpty));
}
IPClose(socket);
}
}
}
void HttpInit(const PageEntry_t *Pages, int UseFiles)
{
HtmlPages = Pages;
HtmlFiles = UseFiles;
IPOpen(IP_MODE_TCP, 0, 80, HttpServer);
IPOpen(IP_MODE_TCP, 0, 8080, HttpServer);
}
#ifdef EXAMPLE_HTML
//Example test code
static void MyProg(IPSocket *socket, char *request, int bytes)
{
char *text="HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"
"<html><body>Hello World!</body></html>";
(void)request; (void)bytes;
IPWrite(socket, (uint8*)text, (int)strlen(text));
IPClose(socket);
}
static const PageEntry_t pageEntry[]=
{ //name, length, htmlText
{"/Header", 0, "<HTML><HEAD><TITLE>Plasma CPU</TITLE></HEAD>\n<BODY>"},
{"/Footer", 0, "</BODY></HTML>"},
{"/ ", 0, "<h2>Home Page</h2>Welcome! <a href='/other.htm'>Other</a>"
" <a href='/cgi/myprog'>myprog</a>"},
{"/other.htm ", 0, "<h2>Other</h2>Other."},
//{"/binary/plasma.gif ", 1945, PlasmaGif},
{"/cgi/myprog", HTML_LENGTH_CALLBACK, (char*)MyProg},
{"", HTML_LENGTH_LIST_END, NULL}
};
void HtmlInit(int UseFiles)
{
(void)UseFiles;
HttpInit(pageEntry, 1);
}
#endif

666
plasma/kernel/libc.c Normal file
View File

@@ -0,0 +1,666 @@
/*--------------------------------------------------------------------
* TITLE: ANSI C Library
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
* DATE CREATED: 12/17/05
* FILENAME: libc.c
* PROJECT: Plasma CPU core
* COPYRIGHT: Software placed into the public domain by the author.
* Software 'as is' without warranty. Author liable for nothing.
* DESCRIPTION:
* Subset of the ANSI C library
*--------------------------------------------------------------------*/
#define NO_ELLIPSIS
#include "rtos.h"
char *strcpy(char *dst, const char *src)
{
char *dstSave=dst;
int c;
do
{
c = *dst++ = *src++;
} while(c);
return dstSave;
}
char *strncpy(char *dst, const char *src, int count)
{
int c=1;
char *dstSave=dst;
while(count-- > 0 && c)
c = *dst++ = *src++;
*dst = 0;
return dstSave;
}
char *strcat(char *dst, const char *src)
{
int c;
char *dstSave=dst;
while(*dst)
++dst;
do
{
c = *dst++ = *src++;
} while(c);
return dstSave;
}
char *strncat(char *dst, const char *src, int count)
{
int c=1;
char *dstSave=dst;
while(*dst && --count > 0)
++dst;
while(--count > 0 && c)
c = *dst++ = *src++;
*dst = 0;
return dstSave;
}
int strcmp(const char *string1, const char *string2)
{
int diff, c;
for(;;)
{
diff = *string1++ - (c = *string2++);
if(diff)
return diff;
if(c == 0)
return 0;
}
}
int strncmp(const char *string1, const char *string2, int count)
{
int diff, c;
while(count-- > 0)
{
diff = *string1++ - (c = *string2++);
if(diff)
return diff;
if(c == 0)
return 0;
}
return 0;
}
char *strstr(const char *string, const char *find)
{
int i;
for(;;)
{
for(i = 0; string[i] == find[i] && find[i]; ++i) ;
if(find[i] == 0)
return (char*)string;
if(*string++ == 0)
return NULL;
}
}
int strlen(const char *string)
{
const char *base=string;
while(*string++) ;
return string - base - 1;
}
void *memcpy(void *dst, const void *src, unsigned long bytes)
{
if(((uint32)dst | (uint32)src | bytes) & 3)
{
uint8 *Dst = (uint8*)dst, *Src = (uint8*)src;
while((int)bytes-- > 0)
*Dst++ = *Src++;
}
else
{
uint32 *Dst32 = (uint32*)dst, *Src32 = (uint32*)src;
bytes >>= 2;
while((int)bytes-- > 0)
*Dst32++ = *Src32++;
}
return dst;
}
void *memmove(void *dst, const void *src, unsigned long bytes)
{
uint8 *Dst = (uint8*)dst;
uint8 *Src = (uint8*)src;
if(Dst < Src)
{
while((int)bytes-- > 0)
*Dst++ = *Src++;
}
else
{
Dst += bytes;
Src += bytes;
while((int)bytes-- > 0)
*--Dst = *--Src;
}
return dst;
}
int memcmp(const void *cs, const void *ct, unsigned long bytes)
{
uint8 *Dst = (uint8*)cs;
uint8 *Src = (uint8*)ct;
int diff;
while((int)bytes-- > 0)
{
diff = *Dst++ - *Src++;
if(diff)
return diff;
}
return 0;
}
void *memset(void *dst, int c, unsigned long bytes)
{
uint8 *Dst = (uint8*)dst;
while((int)bytes-- > 0)
*Dst++ = (uint8)c;
return dst;
}
int abs(int n)
{
return n>=0 ? n : -n;
}
static uint32 Rand1=0x1f2bcda3, Rand2=0xdeafbeef, Rand3=0xc5134306;
int rand(void)
{
int shift;
Rand1 += 0x13423123 + Rand2;
Rand2 += 0x2312fdea + Rand3;
Rand3 += 0xf2a12de1;
shift = Rand3 & 31;
Rand1 = (Rand1 << (32 - shift)) | (Rand1 >> shift);
Rand3 ^= Rand1;
shift = (Rand3 >> 8) & 31;
Rand2 = (Rand2 << (32 - shift)) | (Rand2 >> shift);
return Rand1;
}
void srand(unsigned int seed)
{
Rand1 = seed;
}
long strtol(const char *s, char **end, int base)
{
int i;
unsigned long ch, value=0, neg=0;
if(s[0] == '-')
{
neg = 1;
++s;
}
if(s[0] == '0' && s[1] == 'x')
{
base = 16;
s += 2;
}
for(i = 0; i <= 8; ++i)
{
ch = *s++;
if('0' <= ch && ch <= '9')
ch -= '0';
else if('A' <= ch && ch <= 'Z')
ch = ch - 'A' + 10;
else if('a' <= ch && ch <= 'z')
ch = ch - 'a' + 10;
else
break;
value = value * base + ch;
}
if(end)
*end = (char*)s - 1;
if(neg)
value = -(int)value;
return value;
}
int atoi(const char *s)
{
return strtol(s, NULL, 10);
}
char *itoa(int num, char *dst, int base)
{
int digit, negate=0, place;
char c, text[20];
if(base == 10 && num < 0)
{
num = -num;
negate = 1;
}
text[16] = 0;
for(place = 15; place >= 0; --place)
{
digit = (unsigned int)num % (unsigned int)base;
if(num == 0 && place < 15 && base == 10 && negate)
{
c = '-';
negate = 0;
}
else if(digit < 10)
c = (char)('0' + digit);
else
c = (char)('a' + digit - 10);
text[place] = c;
num = (unsigned int)num / (unsigned int)base;
if(num == 0 && negate == 0)
break;
}
strcpy(dst, text + place);
return dst;
}
int sprintf(char *s, const char *format,
int arg0, int arg1, int arg2, int arg3,
int arg4, int arg5, int arg6, int arg7)
{
int argv[8];
int argc=0, width, length;
char f, text[20], fill;
argv[0] = arg0; argv[1] = arg1; argv[2] = arg2; argv[3] = arg3;
argv[4] = arg4; argv[5] = arg5; argv[6] = arg6; argv[7] = arg7;
for(;;)
{
f = *format++;
if(f == 0)
return argc;
else if(f == '%')
{
width = 0;
fill = ' ';
f = *format++;
while('0' <= f && f <= '9')
{
width = width * 10 + f - '0';
f = *format++;
}
if(f == '.')
{
fill = '0';
f = *format++;
}
if(f == 0)
return argc;
if(f == 'd')
{
memset(s, fill, width);
itoa(argv[argc++], text, 10);
length = (int)strlen(text);
if(width < length)
width = length;
strcpy(s + width - length, text);
}
else if(f == 'x' || f == 'f')
{
memset(s, '0', width);
itoa(argv[argc++], text, 16);
length = (int)strlen(text);
if(width < length)
width = length;
strcpy(s + width - length, text);
}
else if(f == 'c')
{
*s++ = (char)argv[argc++];
*s = 0;
}
else if(f == 's')
{
length = strlen((char*)argv[argc]);
if(width > length)
{
memset(s, ' ', width - length);
s += width - length;
}
strcpy(s, (char*)argv[argc++]);
}
s += strlen(s);
}
else
{
if(f == '\n')
*s++ = '\r';
*s++ = f;
if(f == '\r' && *format == '\n')
*s++ = *format++;
}
*s = 0;
}
}
int sscanf(const char *s, const char *format,
int arg0, int arg1, int arg2, int arg3,
int arg4, int arg5, int arg6, int arg7)
{
int argv[8];
int argc=0;
char f, *ptr;
argv[0] = arg0; argv[1] = arg1; argv[2] = arg2; argv[3] = arg3;
argv[4] = arg4; argv[5] = arg5; argv[6] = arg6; argv[7] = arg7;
for(;;)
{
if(*s == 0)
return argc;
f = *format++;
if(f == 0)
return argc;
else if(f == '%')
{
while(isspace(*s))
++s;
f = *format++;
if(f == 0)
return argc;
if(f == 'd')
*(int*)argv[argc++] = strtol(s, (char**)&s, 10);
else if(f == 'x')
*(int*)argv[argc++] = strtol(s, (char**)&s, 16);
else if(f == 'c')
*(char*)argv[argc++] = *s++;
else if(f == 's')
{
ptr = (char*)argv[argc++];
while(!isspace(*s))
*ptr++ = *s++;
*ptr = 0;
}
}
else
{
while(*s && *s != f)
++s;
if(*s)
++s;
}
}
}
#ifdef INCLUDE_DUMP
/*********************** dump ***********************/
void dump(const unsigned char *data, int length)
{
int i, index=0, value;
char string[80];
memset(string, 0, sizeof(string));
for(i = 0; i < length; ++i)
{
if((i & 15) == 0)
{
if(strlen(string))
printf("%s\n", string);
printf("%4x ", i);
memset(string, 0, sizeof(string));
index = 0;
}
value = data[i];
printf("%2x ", value);
if(isprint(value))
string[index] = (char)value;
else
string[index] = '.';
++index;
}
for(; index < 16; ++index)
printf(" ");
printf("%s\n", string);
}
#endif //INCLUDE_DUMP
#ifdef INCLUDE_QSORT
/*********************** qsort ***********************/
static void QsortSwap(char *base, long left, long right, long size)
{
int temp, i;
char *ptrLeft, *ptrRight;
ptrLeft = base + left * size;
ptrRight = base + right * size;
for(i = 0; i < size; ++i)
{
temp = ptrLeft[i];
ptrLeft[i] = ptrRight[i];
ptrRight[i] = (char)temp;
}
}
//Modified from K&R
static void qsort2(void *base, long left, long right, long size,
int (*cmp)(const void *,const void *))
{
int i, last;
char *base2=(char*)base, *pivot;
if(left >= right)
return;
QsortSwap(base2, left, (left + right)/2, size);
last = left;
pivot = &base2[left*size];
for(i = left + 1; i <= right; ++i)
{
if(cmp(&base2[i*size], pivot) < 0)
QsortSwap(base2, ++last, i, size);
}
QsortSwap(base2, left, last, size);
qsort2(base, left, last-1, size, cmp);
qsort2(base, last+1, right, size, cmp);
}
void qsort(void *base,
long n,
long size,
int (*cmp)(const void *,const void *))
{
qsort2(base, 0, n-1, size, cmp);
}
void *bsearch(const void *key,
const void *base,
long n,
long size,
int (*cmp)(const void *,const void *))
{
long cond, low=0, high=n-1, mid;
char *base2=(char*)base;
while(low <= high)
{
mid = (low + high)/2;
cond = cmp(key, &base2[mid*size]);
if(cond < 0)
high = mid - 1;
else if(cond > 0)
low = mid + 1;
else
return &base2[mid * size];
}
return NULL;
}
#endif //INCLUDE_QSORT
#ifdef INCLUDE_TIMELIB
/************************* time.h ***********************/
#define SEC_PER_YEAR (365L*24*60*60)
#define SEC_PER_DAY (24L*60*60)
//typedef unsigned long time_t; //start at 1/1/80
//struct tm {
// int tm_sec; //(0,59)
// int tm_min; //(0,59)
// int tm_hour; //(0,23)
// int tm_mday; //(1,31)
// int tm_mon; //(0,11)
// int tm_year; //(0,n) from 1900
// int tm_wday; //(0,6) calculated
// int tm_yday; //(0,365) calculated
// int tm_isdst; //hour adjusted for day light savings
//};
static const unsigned short DaysUntilMonth[]=
{0,31,59,90,120,151,181,212,243,273,304,334,365};
static const unsigned short DaysInMonth[]=
{31,28,31,30,31,30,31,31,30,31,30,31};
static time_t DstTimeIn, DstTimeOut;
/* Leap year if divisible by 4. Centenary years should only be
leap-years if they were divisible by 400. */
static int IsLeapYear(int year)
{
return(((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
}
time_t mktime(struct tm *tp)
{
time_t seconds;
unsigned long days, y, year;
days = tp->tm_mday - 1 + DaysUntilMonth[tp->tm_mon] +
365 * (tp->tm_year - 80);
seconds = (unsigned long)tp->tm_sec + 60L * (tp->tm_min +
60L * (tp->tm_hour + 24L * days));
if(tp->tm_isdst)
seconds -= 60 * 60;
year = 1900 + tp->tm_year - (tp->tm_mon < 2);
for(y = 1980; y <= year; y += 4)
{
if(y % 100 != 0 || y % 400 == 0)
seconds += SEC_PER_DAY;
}
return seconds;
}
void gmtime_r(const time_t *tp, struct tm *out)
{
time_t seconds, delta, secondsIn=*tp;
int isLeapYear;
unsigned long year, month;
out->tm_isdst = 0;
if(DstTimeIn <= secondsIn && secondsIn < DstTimeOut)
{
secondsIn += 60 * 60;
out->tm_isdst = 1;
}
seconds = secondsIn;
for(year = 0; ; ++year)
{
delta = SEC_PER_YEAR + IsLeapYear(1980 + year) * SEC_PER_DAY;
if(seconds >= delta)
seconds -= delta;
else
break;
}
out->tm_year = year + 80;
isLeapYear = IsLeapYear(1980 + year);
for(month = 0; ; ++month)
{
delta = SEC_PER_DAY * (DaysInMonth[month] + (isLeapYear && (month == 1)));
if(seconds >= delta)
seconds -= delta;
else
break;
}
out->tm_mon = month;
out->tm_mday = seconds / SEC_PER_DAY;
out->tm_yday = DaysUntilMonth[month] + out->tm_mday;
seconds -= out->tm_mday * SEC_PER_DAY;
++out->tm_mday;
out->tm_hour = seconds / (60 * 60);
seconds -= out->tm_hour * (60 * 60);
out->tm_min = seconds / 60;
seconds -= out->tm_min * 60;
out->tm_sec = seconds;
seconds = secondsIn % (SEC_PER_DAY * 7);
out->tm_wday = (seconds / SEC_PER_DAY + 2) % 7; /* 1/1/80 is a Tue */
//printf("%4.d/%2.d/%2.d:%2.d:%2.d:%2.d\n",
// out->tm_year+1900, out->tm_mon+1, out->tm_mday,
// out->tm_hour, out->tm_min, out->tm_sec);
}
void gmtimeDst(time_t dstTimeIn, time_t dstTimeOut)
{
DstTimeIn = dstTimeIn;
DstTimeOut = dstTimeOut;
}
//DST from 2am on the second Sunday in March to 2am first Sunday in November
void gmtimeDstSet(time_t *tp, time_t *dstTimeIn, time_t *dstTimeOut)
{
time_t seconds, timeIn, timeOut;
struct tm tmDate;
int year, days;
DstTimeIn = 0;
DstTimeOut = 0;
gmtime_r(tp, &tmDate);
year = tmDate.tm_year;
//March 1, year, 2AM -> second Sunday
tmDate.tm_year = year;
tmDate.tm_mon = 2;
tmDate.tm_mday = 1;
tmDate.tm_hour = 2;
tmDate.tm_min = 0;
tmDate.tm_sec = 0;
seconds = mktime(&tmDate);
gmtime_r(&seconds, &tmDate);
days = 7 - tmDate.tm_wday + 7;
*dstTimeIn = timeIn = seconds + days * SEC_PER_DAY;
//November 1, year, 2AM -> first Sunday
tmDate.tm_year = year;
tmDate.tm_mon = 10;
tmDate.tm_mday = 1;
tmDate.tm_hour = 2;
tmDate.tm_min = 0;
tmDate.tm_sec = 0;
seconds = mktime(&tmDate);
gmtime_r(&seconds, &tmDate);
days = 7 - tmDate.tm_wday;
*dstTimeOut = timeOut = seconds + days * SEC_PER_DAY;
DstTimeIn = timeIn;
DstTimeOut = timeOut;
}
#endif //INCLUDE_TIMELIB

192
plasma/kernel/makefile Normal file
View File

@@ -0,0 +1,192 @@
# Makefile for Plasma RTOS and Plasma TCP/IP stack
ifeq ($(LANG),)
# Customize for Windows
# The MIPS gcc compiler must use the cygwin1.dll that came with the compiler.
CC_X86 = cl /O1 /nologo /I..\tools
CP = copy
RM = del
DWIN32 = -DWIN32
BIN_MIPS = ..\gccmips_elf
TOOLS_DIR = ..\tools\\
TOOLS2_DIR = ..\tools
APP_DIR = ..\App\\
LINUX_PWD =
ALIASING =
GCC_MIPS = $(BIN_MIPS)\gcc $(CFLAGS)
AS_MIPS = $(BIN_MIPS)\as
LD_MIPS = $(BIN_MIPS)\ld
DUMP_MIPS = $(BIN_MIPS)\objdump
CONVERT_BIN = $(TOOLS_DIR)convert_bin.exe
OBJ = obj
CFLAGS_X86 = /c /DWIN32
LFLAGS_X86 =
else
# Customized for Linux
# See the GNU GCC tab on the Opencores Plasma page
CC_X86 = gcc -Wall -O -g -I../tools
CP = cp
RM = rm -rf
DWIN32 =
TOOLS_DIR = ../tools/
TOOLS2_DIR = ../tools
APP_DIR = ../App/
LINUX_PWD = ./
ALIASING = -fno-strict-aliasing
GCC_MIPS = $(BIN_MIPS)mips-elf-gcc $(CFLAGS)
AS_MIPS = $(BIN_MIPS)mips-elf-as
LD_MIPS = $(BIN_MIPS)mips-elf-ld
DUMP_MIPS = $(BIN_MIPS)mips-elf-objdump
CONVERT_BIN = $(TOOLS_DIR)convert_bin.exe
#CONVERT_BIN = $(BIN_MIPS)mips-elf-objcopy -I elf32-big -O binary test.axf test.bin
OBJ = o
CFLAGS_X86 = -c -DWIN32 -DLINUX
LFLAGS_X86 = -lm
endif
# Use software multiplier (don't use mult.vhd)
CFLAGS_SW_MULT = -mno-mul -DUSE_SW_MULT
# Use 16 fewer registers (make reg_bank.vhd smaller)
CFLAGS_FEW_REGS = -ffixed-t0 -ffixed-t1 -ffixed-t2 -ffixed-t3 -ffixed-t4 -ffixed-t5 -ffixed-t6 -ffixed-t7 -ffixed-s0 -ffixed-s1 -ffixed-s2 -ffixed-s3 -ffixed-s4 -ffixed-s5 -ffixed-s6 -ffixed-s7
CFLAGS = -O2 -Wall -c -s -I$(TOOLS2_DIR) -msoft-float -fno-builtin
#CFLAGS += $(CFLAGS_SW_MULT)
#CFLAGS += $(CFLAGS_FEW_REGS)
# Build just the Plasma RTOS for Plasma CPU
rtos:
$(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm
$(GCC_MIPS) rtos.c
$(GCC_MIPS) libc.c
$(GCC_MIPS) uart.c
$(GCC_MIPS) rtos_test.c
$(GCC_MIPS) math.c $(ALIASING)
$(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \
boot.o rtos.o libc.o uart.o rtos_test.o math.o
$(CONVERT_BIN)
@sort <test.map >test2.map
@$(DUMP_MIPS) --disassemble test.axf > test.lst
# Build the Plasma RTOS, Plasma TCP/IP stack, and web server for the Plasma CPU
# Use the serial port and etermip for TCP/IP packets
rtos_tcpip:
$(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm
$(GCC_MIPS) rtos.c
$(GCC_MIPS) libc.c
$(GCC_MIPS) uart.c
$(GCC_MIPS) rtos_test.c -DINCLUDE_HTML -DINCLUDE_CONSOLE
$(GCC_MIPS) math.c $(ALIASING)
$(GCC_MIPS) tcpip.c -DINCLUDE_FILESYS
$(GCC_MIPS) http.c -DINCLUDE_FILESYS -DEXAMPLE_HTML
$(GCC_MIPS) netutil.c
$(GCC_MIPS) filesys.c
$(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \
boot.o rtos.o libc.o uart.o rtos_test.o math.o tcpip.o \
http.o netutil.o filesys.o
$(CONVERT_BIN)
@sort <test.map >test2.map
@$(DUMP_MIPS) --disassemble test.axf > test.lst
# Use Ethernet for TCP/IP packets, use flash file system
rtos_tcpip_eth:
$(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm
$(GCC_MIPS) rtos.c
$(GCC_MIPS) libc.c
$(GCC_MIPS) uart.c -DNO_PACKETS
$(GCC_MIPS) rtos_test.c -DINCLUDE_ETH -DINCLUDE_CONSOLE
$(GCC_MIPS) math.c $(ALIASING)
$(GCC_MIPS) tcpip.c -DINCLUDE_FILESYS
$(GCC_MIPS) http.c -DINCLUDE_FILESYS -DEXAMPLE_HTML
$(GCC_MIPS) netutil.c -DINCLUDE_FLASH -DDLL_SETUP
$(GCC_MIPS) filesys.c -DINCLUDE_FLASH
$(GCC_MIPS) ethernet.c
$(GCC_MIPS) flash.c
$(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \
boot.o rtos.o libc.o uart.o rtos_test.o math.o tcpip.o \
http.o netutil.o filesys.o ethernet.o flash.o
$(CONVERT_BIN)
@sort <test.map >test2.map
@$(DUMP_MIPS) --disassemble test.axf > test.lst
# Build full test application
rtosfull:
$(AS_MIPS) -o boot.o $(TOOLS_DIR)boot.asm
$(GCC_MIPS) rtos.c
$(GCC_MIPS) libc.c
$(GCC_MIPS) uart.c -DNO_PACKETS
$(GCC_MIPS) rtos_test.c -DINCLUDE_ETH -DINCLUDE_CONSOLE
$(GCC_MIPS) math.c $(ALIASING)
$(GCC_MIPS) tcpip.c -DINCLUDE_FILESYS
$(GCC_MIPS) http.c -DINCLUDE_FILESYS
$(GCC_MIPS) netutil.c -DINCLUDE_FLASH -DDLL_SETUP
$(GCC_MIPS) filesys.c -DINCLUDE_FLASH
$(GCC_MIPS) ethernet.c
$(GCC_MIPS) flash.c
$(GCC_MIPS) -I. $(APP_DIR)html.c -DMainThread=HtmlThread
$(GCC_MIPS) -I. $(APP_DIR)image.c
$(GCC_MIPS) -I. $(APP_DIR)tictac.c
$(GCC_MIPS) -I. $(APP_DIR)tic3d.c
$(GCC_MIPS) -I. $(APP_DIR)connect4.c
$(LD_MIPS) -Ttext 0x10000000 -eentry -Map test.map -s -N -o test.axf \
boot.o rtos.o libc.o uart.o rtos_test.o math.o tcpip.o \
http.o netutil.o filesys.o ethernet.o flash.o \
html.o image.o tictac.o tic3d.o connect4.o
$(CONVERT_BIN)
@sort <test.map >test2.map
@$(DUMP_MIPS) --disassemble test.axf > test.lst
# Create a separate Dynamically Linked Library executable
# ftp test.bin to /flash/web/dlltest
# telnet to board and execute "dlltest"
dlltest:
$(GCC_MIPS) -G0 dlltest.c
$(LD_MIPS) -Ttext 0x10100000 -s -N -o test.axf dlltest.o
$(CONVERT_BIN)
@$(DUMP_MIPS) --disassemble test.axf > test.lst
# Test the RTOS running on a PC
testrtos:
@$(CC_X86) $(CFLAGS_X86) rtos.c
@$(CC_X86) $(CFLAGS_X86) libc.c
@$(CC_X86) $(CFLAGS_X86) uart.c
@$(CC_X86) $(CFLAGS_X86) rtos_test.c
@$(CC_X86) $(CFLAGS_X86) math.c $(ALIASING)
@$(CC_X86) $(LFLAGS_X86) -o testrtos.exe rtos.$(OBJ) libc.$(OBJ) uart.$(OBJ) rtos_test.$(OBJ) math.$(OBJ)
$(LINUX_PWD)testrtos.exe
# Test the TCP/IP protocol stack running on a PC (requires Windows)
testip:
@$(CC_X86) $(CFLAGS_X86) tcpip.c
@$(CC_X86) $(CFLAGS_X86) http.c /DEXAMPLE_HTML
@$(CC_X86) $(CFLAGS_X86) netutil.c
@$(CC_X86) $(CFLAGS_X86) filesys.c
@$(CC_X86) $(CFLAGS_X86) libc.c /I$(TOOLS_DIR)
@$(CC_X86) $(CFLAGS_X86) /DSIMULATE_PLASMA $(TOOLS_DIR)etermip.c
@$(CC_X86) $(CFLAGS_X86) os_stubs.c
@$(CC_X86) -o testip.exe etermip.obj $(TOOLS_DIR)wpcap.lib \
tcpip.obj http.obj netutil.obj filesys.obj libc.obj os_stubs.obj
@echo Try http://plasmb/. Try telnet plasmb. Try ftp plasmb.
$(LINUX_PWD)testip.exe
clean:
-$(RM) *.o *.obj *.axf *.map *.lst *.hex *.txt *.bin *.exe
# Run a Plasma CPU opcode simulator (can execute rtos target)
run:
@$(TOOLS_DIR)mlite.exe test.bin
disassemble:
-@$(TOOLS_DIR)mlite.exe test.bin BD > test.txt
# Start the EtermIP terminal program to download the code to the Plasma CPU
# and permit an Ethernet packets to be transfered.
download:
@echo Reset board before downloading code
$(TOOLS_DIR)etermip.exe

692
plasma/kernel/math.c Normal file
View File

@@ -0,0 +1,692 @@
/*--------------------------------------------------------------------
* TITLE: Plasma Floating Point Library
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
* DATE CREATED: 3/2/06
* FILENAME: math.c
* PROJECT: Plasma CPU core
* COPYRIGHT: Software placed into the public domain by the author.
* Software 'as is' without warranty. Author liable for nothing.
* DESCRIPTION:
* Plasma Floating Point Library
*--------------------------------------------------------------------
* IEEE_fp = sign(1) | exponent(8) | fraction(23)
* cos(x)=1-x^2/2!+x^4/4!-x^6/6!+...
* exp(x)=1+x+x^2/2!+x^3/3!+...
* ln(1+x)=x-x^2/2+x^3/3-x^4/4+...
* atan(x)=x-x^3/3+x^5/5-x^7/7+...
* pow(x,y)=exp(y*ln(x))
* x=tan(a+b)=(tan(a)+tan(b))/(1-tan(a)*tan(b))
* atan(x)=b+atan((x-atan(b))/(1+x*atan(b)))
* ln(a*x)=ln(a)+ln(x); ln(x^n)=n*ln(x)
*--------------------------------------------------------------------*/
#include "rtos.h"
//#define USE_SW_MULT
#if !defined(WIN32) && !defined(USE_SW_MULT)
#define USE_MULT64
#endif
#define PI ((float)3.1415926)
#define PI_2 ((float)(PI/2.0))
#define PI2 ((float)(PI*2.0))
#define FtoL(X) (*(unsigned long*)&(X))
#define LtoF(X) (*(float*)&(X))
float FP_Neg(float a_fp)
{
unsigned long a;
a = FtoL(a_fp);
a ^= 0x80000000;
return LtoF(a);
}
float FP_Add(float a_fp, float b_fp)
{
unsigned long a, b, c;
unsigned long as, bs, cs; //sign
long ae, af, be, bf, ce, cf; //exponent and fraction
a = FtoL(a_fp);
b = FtoL(b_fp);
as = a >> 31; //sign
ae = (a >> 23) & 0xff; //exponent
af = 0x00800000 | (a & 0x007fffff); //fraction
bs = b >> 31;
be = (b >> 23) & 0xff;
bf = 0x00800000 | (b & 0x007fffff);
if(ae > be)
{
if(ae - be < 30)
bf >>= ae - be;
else
bf = 0;
ce = ae;
}
else
{
if(be - ae < 30)
af >>= be - ae;
else
af = 0;
ce = be;
}
cf = (as ? -af : af) + (bs ? -bf : bf);
cs = cf < 0;
cf = cf>=0 ? cf : -cf;
if(cf == 0)
return LtoF(cf);
while(cf & 0xff000000)
{
++ce;
cf >>= 1;
}
while((cf & 0xff800000) == 0)
{
--ce;
cf <<= 1;
}
c = (cs << 31) | (ce << 23) | (cf & 0x007fffff);
if(ce < 1)
c = 0;
return LtoF(c);
}
float FP_Sub(float a_fp, float b_fp)
{
return FP_Add(a_fp, FP_Neg(b_fp));
}
float FP_Mult(float a_fp, float b_fp)
{
unsigned long a, b, c;
unsigned long as, af, bs, bf, cs, cf;
long ae, be, ce;
#ifndef USE_MULT64
unsigned long a2, a1, b2, b1, med1, med2;
#endif
unsigned long hi, lo;
a = FtoL(a_fp);
b = FtoL(b_fp);
as = a >> 31;
ae = (a >> 23) & 0xff;
af = 0x00800000 | (a & 0x007fffff);
bs = b >> 31;
be = (b >> 23) & 0xff;
bf = 0x00800000 | (b & 0x007fffff);
cs = as ^ bs;
#ifndef USE_MULT64
a1 = af & 0xffff;
a2 = af >> 16;
b1 = bf & 0xffff;
b2 = bf >> 16;
lo = a1 * b1;
med1 = a2 * b1 + (lo >> 16);
med2 = a1 * b2;
hi = a2 * b2 + (med1 >> 16) + (med2 >> 16);
med1 = (med1 & 0xffff) + (med2 & 0xffff);
hi += (med1 >> 16);
lo = (med1 << 16) | (lo & 0xffff);
#else
lo = OS_AsmMult(af, bf, &hi);
#endif
cf = (hi << 9) | (lo >> 23);
ce = ae + be - 0x80 + 1;
if(cf == 0)
return LtoF(cf);
while(cf & 0xff000000)
{
++ce;
cf >>= 1;
}
c = (cs << 31) | (ce << 23) | (cf & 0x007fffff);
if(ce < 1)
c = 0;
return LtoF(c);
}
float FP_Div(float a_fp, float b_fp)
{
unsigned long a, b, c;
unsigned long as, af, bs, bf, cs, cf;
unsigned long a1, b1;
#ifndef USE_MULT64
unsigned long a2, b2, med1, med2;
#endif
unsigned long hi, lo;
long ae, be, ce, d;
a = FtoL(a_fp);
b = FtoL(b_fp);
as = a >> 31;
ae = (a >> 23) & 0xff;
af = 0x00800000 | (a & 0x007fffff);
bs = b >> 31;
be = (b >> 23) & 0xff;
bf = 0x00800000 | (b & 0x007fffff);
cs = as ^ bs;
ce = ae - (be - 0x80) + 6 - 8;
a1 = af << 4; //8
b1 = bf >> 8;
cf = a1 / b1;
cf <<= 12; //8
#if 1 /*non-quick*/
#ifndef USE_MULT64
a1 = cf & 0xffff;
a2 = cf >> 16;
b1 = bf & 0xffff;
b2 = bf >> 16;
lo = a1 * b1;
med1 =a2 * b1 + (lo >> 16);
med2 = a1 * b2;
hi = a2 * b2 + (med1 >> 16) + (med2 >> 16);
med1 = (med1 & 0xffff) + (med2 & 0xffff);
hi += (med1 >> 16);
lo = (med1 << 16) | (lo & 0xffff);
#else
lo = OS_AsmMult(cf, bf, &hi);
#endif
lo = (hi << 8) | (lo >> 24);
d = af - lo; //remainder
assert(-0xffff < d && d < 0xffff);
d <<= 16;
b1 = bf >> 8;
d = d / (long)b1;
cf += d;
#endif
if(cf == 0)
return LtoF(cf);
while(cf & 0xff000000)
{
++ce;
cf >>= 1;
}
if(ce < 0)
ce = 0;
c = (cs << 31) | (ce << 23) | (cf & 0x007fffff);
if(ce < 1)
c = 0;
return LtoF(c);
}
long FP_ToLong(float a_fp)
{
unsigned long a;
unsigned long as;
long ae;
long af, shift;
a = FtoL(a_fp);
as = a >> 31;
ae = (a >> 23) & 0xff;
af = 0x00800000 | (a & 0x007fffff);
af <<= 7;
shift = -(ae - 0x80 - 29);
if(shift > 0)
{
if(shift < 31)
af >>= shift;
else
af = 0;
}
af = as ? -af: af;
return af;
}
float FP_ToFloat(long af)
{
unsigned long a;
unsigned long as, ae;
as = af>=0 ? 0: 1;
af = af>=0 ? af: -af;
ae = 0x80 + 22;
if(af == 0)
return LtoF(af);
while(af & 0xff000000)
{
++ae;
af >>= 1;
}
while((af & 0xff800000) == 0)
{
--ae;
af <<= 1;
}
a = (as << 31) | (ae << 23) | (af & 0x007fffff);
return LtoF(a);
}
//0 iff a==b; 1 iff a>b; -1 iff a<b
int FP_Cmp(float a_fp, float b_fp)
{
unsigned long a, b;
unsigned long as, ae, af, bs, be, bf;
int gt;
a = FtoL(a_fp);
b = FtoL(b_fp);
if(a == b)
return 0;
as = a >> 31;
bs = b >> 31;
if(as > bs)
return -1;
if(as < bs)
return 1;
gt = as ? -1 : 1;
ae = (a >> 23) & 0xff;
be = (b >> 23) & 0xff;
if(ae > be)
return gt;
if(ae < be)
return -gt;
af = 0x00800000 | (a & 0x007fffff);
bf = 0x00800000 | (b & 0x007fffff);
if(af > bf)
return gt;
return -gt;
}
int __ltsf2(float a, float b)
{
return FP_Cmp(a, b);
}
int __lesf2(float a, float b)
{
return FP_Cmp(a, b);
}
int __gtsf2(float a, float b)
{
return FP_Cmp(a, b);
}
int __gesf2(float a, float b)
{
return FP_Cmp(a, b);
}
int __eqsf2(float a, float b)
{
return FtoL(a) != FtoL(b);
}
int __nesf2(float a, float b)
{
return FtoL(a) != FtoL(b);
}
float FP_Sqrt(float a)
{
float x1, y1, x2, y2, x3;
long i;
x1 = FP_ToFloat(1);
y1 = FP_Sub(FP_Mult(x1, x1), a); //y1=x1*x1-a;
x2 = FP_ToFloat(100);
y2 = FP_Sub(FP_Mult(x2, x2), a);
for(i = 0; i < 10; ++i)
{
if(FtoL(y1) == FtoL(y2))
return x2;
//x3=x2-(x1-x2)*y2/(y1-y2);
x3 = FP_Sub(x2, FP_Div(FP_Mult(FP_Sub(x1, x2), y2), FP_Sub(y1, y2)));
x1 = x2;
y1 = y2;
x2 = x3;
y2 = FP_Sub(FP_Mult(x2, x2), a);
}
return x2;
}
float FP_Cos(float rad)
{
int n;
float answer, x2, top, bottom, sign;
while(FP_Cmp(rad, PI2) > 0)
rad = FP_Sub(rad, PI2);
while(FP_Cmp(rad, (float)0.0) < 0)
rad = FP_Add(rad, PI2);
answer = 1.0;
sign = 1.0;
if(FP_Cmp(rad, PI) >= 0)
{
rad = FP_Sub(rad, PI);
sign = FP_ToFloat(-1);
}
if(FP_Cmp(rad, PI_2) >= 0)
{
rad = FP_Sub(PI, rad);
sign = FP_Neg(sign);
}
x2 = FP_Mult(rad, rad);
top = 1.0;
bottom = 1.0;
for(n = 2; n < 12; n += 2)
{
top = FP_Mult(top, FP_Neg(x2));
bottom = FP_Mult(bottom, FP_ToFloat((n - 1) * n));
answer = FP_Add(answer, FP_Div(top, bottom));
}
return FP_Mult(answer, sign);
}
float FP_Sin(float rad)
{
const float pi_2=(float)(PI/2.0);
return FP_Cos(FP_Sub(rad, pi_2));
}
float FP_Atan(float x)
{
const float b=(float)(PI/8.0);
const float atan_b=(float)0.37419668; //atan(b);
int n;
float answer, x2, top;
if(FP_Cmp(x, (float)0.0) >= 0)
{
if(FP_Cmp(x, (float)1.0) > 0)
return FP_Sub(PI_2, FP_Atan(FP_Div((float)1.0, x)));
}
else
{
if(FP_Cmp(x, (float)-1.0) > 0)
return FP_Sub(-PI_2, FP_Atan(FP_Div((float)1.0, x)));
}
if(FP_Cmp(x, (float)0.45) > 0)
{
//answer = (x - atan_b) / (1 + x * atan_b);
answer = FP_Div(FP_Sub(x, atan_b), FP_Add(1.0, FP_Mult(x, atan_b)));
//answer = b + FP_Atan(answer) - (float)0.034633; /*FIXME fudge?*/
answer = FP_Sub(FP_Add(b, FP_Atan(answer)), (float)0.034633);
return answer;
}
if(FP_Cmp(x, (float)-0.45) < 0)
{
x = FP_Neg(x);
//answer = (x - atan_b) / (1 + x * atan_b);
answer = FP_Div(FP_Sub(x, atan_b), FP_Add(1.0, FP_Mult(x, atan_b)));
//answer = b + FP_Atan(answer) - (float)0.034633; /*FIXME*/
answer = FP_Sub(FP_Add(b, FP_Atan(answer)), (float)0.034633);
return FP_Neg(answer);
}
answer = x;
x2 = FP_Mult(FP_Neg(x), x);
top = x;
for(n = 3; n < 14; n += 2)
{
top = FP_Mult(top, x2);
answer = FP_Add(answer, FP_Div(top, FP_ToFloat(n)));
}
return answer;
}
float FP_Atan2(float y, float x)
{
float answer,r;
r = y / x;
answer = FP_Atan(r);
if(FP_Cmp(x, (float)0.0) < 0)
{
if(FP_Cmp(y, (float)0.0) > 0)
answer = FP_Add(answer, PI);
else
answer = FP_Sub(answer, PI);
}
return answer;
}
float FP_Exp(float x)
{
const float e2=(float)7.389056099;
const float inv_e2=(float)0.135335283;
float answer, top, bottom, mult;
int n;
mult = 1.0;
while(FP_Cmp(x, (float)2.0) > 0)
{
mult = FP_Mult(mult, e2);
x = FP_Add(x, (float)-2.0);
}
while(FP_Cmp(x, (float)-2.0) < 0)
{
mult = FP_Mult(mult, inv_e2);
x = FP_Add(x, (float)2.0);
}
answer = FP_Add((float)1.0, x);
top = x;
bottom = 1.0;
for(n = 2; n < 15; ++n)
{
top = FP_Mult(top, x);
bottom = FP_Mult(bottom, FP_ToFloat(n));
answer = FP_Add(answer, FP_Div(top, bottom));
}
return FP_Mult(answer, mult);
}
float FP_Log(float x)
{
const float log_2=(float)0.69314718; /*log(2.0)*/
int n;
float answer, top, add;
add = 0.0;
while(FP_Cmp(x, 16.0) > 0)
{
x = FP_Mult(x, (float)0.0625);
add = FP_Add(add, (float)(log_2 * 4));
}
while(FP_Cmp(x, 1.5) > 0)
{
x = FP_Mult(x, 0.5);
add = FP_Add(add, log_2);
}
while(FP_Cmp(x, 0.5) < 0)
{
x = FP_Mult(x, 2.0);
add = FP_Sub(add, log_2);
}
x = FP_Sub(x, 1.0);
answer = 0.0;
top = -1.0;
for(n = 1; n < 14; ++n)
{
top = FP_Mult(top, FP_Neg(x));
answer = FP_Add(answer, FP_Div(top, FP_ToFloat(n)));
}
return FP_Add(answer, add);
}
float FP_Pow(float x, float y)
{
return FP_Exp(y * FP_Log(x));
}
/********************************************/
//These five functions will only be used if the flag "-mno-mul" is enabled
#ifdef USE_SW_MULT
unsigned long __mulsi3(unsigned long a, unsigned long b)
{
unsigned long answer = 0;
while(b)
{
if(b & 1)
answer += a;
a <<= 1;
b >>= 1;
}
return answer;
}
static unsigned long DivideMod(unsigned long a, unsigned long b, int doMod)
{
unsigned long upper=a, lower=0;
int i;
a = b << 31;
for(i = 0; i < 32; ++i)
{
lower = lower << 1;
if(upper >= a && a && b < 2)
{
upper = upper - a;
lower |= 1;
}
a = ((b&2) << 30) | (a >> 1);
b = b >> 1;
}
if(!doMod)
return lower;
return upper;
}
unsigned long __udivsi3(unsigned long a, unsigned long b)
{
return DivideMod(a, b, 0);
}
long __divsi3(long a, long b)
{
long answer, negate=0;
if(a < 0)
{
a = -a;
negate = !negate;
}
if(b < 0)
{
b = -b;
negate = !negate;
}
answer = DivideMod(a, b, 0);
if(negate)
answer = -answer;
return answer;
}
unsigned long __umodsi3(unsigned long a, unsigned long b)
{
return DivideMod(a, b, 1);
}
#endif
/*************** Test *****************/
#ifdef WIN32
#undef _LIBC
#include <math.h>
#undef printf
#undef getch
int printf(const char *, ...);
struct {
char *name;
float low, high;
double (*func1)(double);
float (*func2)(float);
} test_info[]={
{"cos", -2*PI, 2*PI, cos, FP_Cos},
{"sin", -2*PI, 2*PI, sin, FP_Sin},
{"atan", -3.0, 2.0, atan, FP_Atan},
{"log", (float)0.01, (float)4.0, log, FP_Log},
{"exp", (float)-5.01, (float)30.0, exp, FP_Exp},
{"sqrt", (float)0.01, (float)1000.0, sqrt, FP_Sqrt}
};
void TestMathFull(void)
{
float a, b, c, d;
float error1, error2, error3, error4, error5;
int test;
a = PI * PI;
b = PI;
c = FP_Div(a, b);
printf("%10f %10f %10f %10f %10f\n",
(double)a, (double)b, (double)(a/b), (double)c, (double)(a/b-c));
a = a * 200;
for(b = -(float)2.718281828*100; b < 300; b += (float)23.678)
{
c = FP_Div(a, b);
d = a / b - c;
printf("%10f %10f %10f %10f %10f\n",
(double)a, (double)b, (double)(a/b), (double)c, (double)(a/b-c));
}
//getch();
for(test = 0; test < 6; ++test)
{
printf("\nTesting %s\n", test_info[test].name);
for(a = test_info[test].low;
a <= test_info[test].high;
a += (test_info[test].high-test_info[test].low)/(float)20.0)
{
b = (float)test_info[test].func1(a);
c = test_info[test].func2(a);
d = b - c;
printf("%s %10f %10f %10f %10f\n", test_info[test].name, a, b, c, d);
}
//getch();
}
a = FP_ToFloat((long)6.0);
b = FP_ToFloat((long)2.0);
printf("%f %f\n", (double)a, (double)b);
c = FP_Add(a, b);
printf("add %f %f\n", (double)(a + b), (double)c);
c = FP_Sub(a, b);
printf("sub %f %f\n", (double)(a - b), (double)c);
c = FP_Mult(a, b);
printf("mult %f %f\n", (double)(a * b), (double)c);
c = FP_Div(a, b);
printf("div %f %f\n", (double)(a / b), (double)c);
//getch();
for(a = (float)-13756.54; a < (float)17400.0; a += (float)64.45)
{
for(b = (float)-875.36; b < (float)935.8; b += (float)36.7)
{
error1 = (float)1.0 - (a + b) / FP_Add(a, b);
error2 = (float)1.0 - (a * b) / FP_Mult(a, b);
error3 = (float)1.0 - (a / b) / FP_Div(a, b);
error4 = (float)1.0 - a / FP_ToFloat(FP_ToLong(a));
error5 = error1 + error2 + error3 + error4;
if(error5 < 0.00005)
continue;
printf("ERROR!\n");
printf("a=%f b=%f\n", (double)a, (double)b);
printf(" a+b=%f %f\n", (double)(a+b), (double)FP_Add(a, b));
printf(" a*b=%f %f\n", (double)(a*b), (double)FP_Mult(a, b));
printf(" a/b=%f %f\n", (double)(a/b), (double)FP_Div(a, b));
printf(" a=%f %ld %f\n", (double)a, FP_ToLong(a),
(double)FP_ToFloat((long)a));
printf(" %f %f %f %f\n", (double)error1, (double)error2,
(double)error3, (double)error4);
//if(error5 > 0.001)
// getch();
}
}
printf("done.\n");
//getch();
}
#endif

1159
plasma/kernel/netutil.c Normal file

File diff suppressed because it is too large Load Diff

71
plasma/kernel/os_stubs.c Normal file
View File

@@ -0,0 +1,71 @@
/*--------------------------------------------------------------------
* TITLE: OS stubs
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
* DATE CREATED: 2/18/08
* FILENAME: os_stubs.c
* PROJECT: Plasma CPU core
* COPYRIGHT: Software placed into the public domain by the author.
* Software 'as is' without warranty. Author liable for nothing.
* DESCRIPTION:
*--------------------------------------------------------------------*/
#include <stdlib.h>
#include "plasma.h"
#include "rtos.h"
unsigned char *flash;
int beenInit;
void FlashRead(uint16 *dst, uint32 byteOffset, int bytes)
{
if(beenInit == 0)
{
beenInit = 1;
flash = (unsigned char*)malloc(1024*1024*16);
memset(flash, 0xff, sizeof(flash));
}
memcpy(dst, flash+byteOffset, bytes);
}
void FlashWrite(uint16 *src, uint32 byteOffset, int bytes)
{
memcpy(flash+byteOffset, src, bytes);
}
void FlashErase(uint32 byteOffset)
{
memset(flash+byteOffset, 0xff, 1024*128);
}
//Stub out RTOS functions
void UartPrintfCritical(const char *format, ...) {(void)format;}
uint32 OS_AsmInterruptEnable(uint32 state) {(void)state; return 0;}
void OS_Assert(void) {}
OS_Thread_t *OS_ThreadSelf(void) {return NULL;}
void OS_ThreadSleep(int ticks) {(void)ticks;}
uint32 OS_ThreadTime(void) {return 0;}
OS_Mutex_t *OS_MutexCreate(const char *name) {(void)name; return NULL; }
void OS_MutexDelete(OS_Mutex_t *semaphore) {(void)semaphore;}
void OS_MutexPend(OS_Mutex_t *semaphore) {(void)semaphore;}
void OS_MutexPost(OS_Mutex_t *semaphore) {(void)semaphore;}
OS_MQueue_t *OS_MQueueCreate(const char *name,
int messageCount,
int messageBytes)
{(void)name;(void)messageCount;(void)messageBytes; return NULL;}
void OS_MQueueDelete(OS_MQueue_t *mQueue) {(void)mQueue;}
int OS_MQueueSend(OS_MQueue_t *mQueue, void *message)
{(void)mQueue;(void)message; return 0;}
int OS_MQueueGet(OS_MQueue_t *mQueue, void *message, int ticks)
{(void)mQueue;(void)message;(void)ticks; return 0;}
void OS_Job(void (*funcPtr)(), void *arg0, void *arg1, void *arg2)
{funcPtr(arg0, arg1, arg2);}

1467
plasma/kernel/rtos.c Normal file

File diff suppressed because it is too large Load Diff

377
plasma/kernel/rtos.h Normal file
View File

@@ -0,0 +1,377 @@
/*--------------------------------------------------------------------
* TITLE: Plasma Real Time Operating System
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
* DATE CREATED: 12/17/05
* FILENAME: rtos.h
* PROJECT: Plasma CPU core
* COPYRIGHT: Software placed into the public domain by the author.
* Software 'as is' without warranty. Author liable for nothing.
* DESCRIPTION:
* Plasma Real Time Operating System
*--------------------------------------------------------------------*/
#ifndef __RTOS_H__
#define __RTOS_H__
// Symmetric Multi-Processing
#define OS_CPU_COUNT 1
// Typedefs
typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
// Memory Access
#ifdef WIN32
uint32 MemoryRead(uint32 Address);
void MemoryWrite(uint32 Address, uint32 Value);
#else
#define MemoryRead(A) (*(volatile uint32*)(A))
#define MemoryWrite(A,V) *(volatile uint32*)(A)=(V)
#endif
/***************** LibC ******************/
#if !defined(_LIBC) && !defined(_CTYPE_DEFINED)
#define printf UartPrintf
//#define printf UartPrintfPoll
#define scanf UartScanf
#ifndef WIN32
#define malloc(S) OS_HeapMalloc(NULL, S)
#define free(S) OS_HeapFree(S)
#endif
#ifndef NULL
#define NULL (void*)0
#endif
#define assert(A) if((A)==0){OS_Assert();UartPrintfCritical("\r\nAssert %s:%d\r\n", __FILE__, __LINE__);}
#define isprint(c) (' '<=(c)&&(c)<='~')
#define isspace(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\r')
#define isdigit(c) ('0'<=(c)&&(c)<='9')
#define islower(c) ('a'<=(c)&&(c)<='z')
#define isupper(c) ('A'<=(c)&&(c)<='Z')
#define isalpha(c) (islower(c)||isupper(c))
#define isalnum(c) (isalpha(c)||isdigit(c))
#undef min
#define min(a,b) ((a)<(b)?(a):(b))
#define strcpy strcpy2 //don't use intrinsic functions
#define strcat strcat2
#define strncat strncat2
#define strcmp strcmp2
#define strlen strlen2
#define memcpy memcpy2
#define memcmp memcmp2
#define memset memset2
#define abs abs2
#define atoi atoi2
char *strcpy(char *dst, const char *src);
char *strncpy(char *dst, const char *src, int count);
char *strcat(char *dst, const char *src);
char *strncat(char *dst, const char *src, int count);
int strcmp(const char *string1, const char *string2);
int strncmp(const char *string1, const char *string2, int count);
char *strstr(const char *string, const char *find);
int strlen(const char *string);
void *memcpy(void *dst, const void *src, unsigned long bytes);
void *memmove(void *dst, const void *src, unsigned long bytes);
int memcmp(const void *cs, const void *ct, unsigned long bytes);
void *memset(void *dst, int c, unsigned long bytes);
int abs(int n);
int rand(void);
void srand(unsigned int seed);
long strtol(const char *s, char **end, int base);
int atoi(const char *s);
char *itoa(int num, char *dst, int base);
#ifndef NO_ELLIPSIS
int sprintf(char *s, const char *format, ...);
int sscanf(const char *s, const char *format, ...);
#endif
#ifdef INCLUDE_DUMP
void dump(const unsigned char *data, int length);
#endif
#ifdef INCLUDE_QSORT
void qsort(void *base,
long n,
long size,
int (*cmp)(const void *,const void *));
void *bsearch(const void *key,
const void *base,
long n,
long size,
int (*cmp)(const void *,const void *));
#endif
#ifdef INCLUDE_TIMELIB
#define difftime(time2,time1) (time2-time1)
typedef unsigned long time_t; //start at 1/1/80
struct tm {
int tm_sec; //(0,59)
int tm_min; //(0,59)
int tm_hour; //(0,23)
int tm_mday; //(1,31)
int tm_mon; //(0,11)
int tm_year; //(0,n) from 1900
int tm_wday; //(0,6) calculated
int tm_yday; //(0,365) calculated
int tm_isdst; // calculated
};
time_t mktime(struct tm *tp);
void gmtime_r(const time_t *tp, struct tm *out);
void gmtimeDst(time_t dstTimeIn, time_t dstTimeOut);
void gmtimeDstSet(time_t *tp, time_t *dstTimeIn, time_t *dstTimeOut);
#endif
#define _LIBC
#endif //_LIBC
/***************** Assembly **************/
typedef uint32 jmp_buf[20];
extern uint32 OS_AsmInterruptEnable(uint32 state);
extern void OS_AsmInterruptInit(void);
extern int setjmp(jmp_buf env);
extern void longjmp(jmp_buf env, int val);
extern uint32 OS_AsmMult(uint32 a, uint32 b, unsigned long *hi);
extern void *OS_Syscall();
/***************** Heap ******************/
#define HEAP_USER (void*)0
#define HEAP_SYSTEM (void*)1
#define HEAP_SMALL (void*)2
#define HEAP_UI (void*)3
typedef struct OS_Heap_s OS_Heap_t;
OS_Heap_t *OS_HeapCreate(const char *name, void *memory, uint32 size);
void OS_HeapDestroy(OS_Heap_t *heap);
void *OS_HeapMalloc(OS_Heap_t *heap, int bytes);
void OS_HeapFree(void *block);
void OS_HeapAlternate(OS_Heap_t *heap, OS_Heap_t *alternate);
void OS_HeapRegister(void *index, OS_Heap_t *heap);
/***************** Critical Sections *****************/
#if OS_CPU_COUNT <= 1
// Single CPU
#define OS_CpuIndex() 0
#define OS_CriticalBegin() OS_AsmInterruptEnable(0)
#define OS_CriticalEnd(S) OS_AsmInterruptEnable(S)
#define OS_SpinLock() 0
#define OS_SpinUnlock(S)
#else
// Symmetric multiprocessing
uint32 OS_CpuIndex(void);
#define OS_CriticalBegin() OS_SpinLock()
#define OS_CriticalEnd(S) OS_SpinUnlock(S)
uint32 OS_SpinLock(void);
void OS_SpinUnlock(uint32 state);
#endif
/***************** Thread *****************/
#ifdef WIN32
#define STACK_SIZE_MINIMUM (1024*4)
#else
#define STACK_SIZE_MINIMUM (1024*1)
#endif
#define STACK_SIZE_DEFAULT 1024*2
#undef THREAD_PRIORITY_IDLE
#define THREAD_PRIORITY_IDLE 0
#define THREAD_PRIORITY_MAX 255
typedef void (*OS_FuncPtr_t)(void *arg);
typedef struct OS_Thread_s OS_Thread_t;
OS_Thread_t *OS_ThreadCreate(const char *name,
OS_FuncPtr_t funcPtr,
void *arg,
uint32 priority,
uint32 stackSize);
void OS_ThreadExit(void);
OS_Thread_t *OS_ThreadSelf(void);
void OS_ThreadSleep(int ticks);
uint32 OS_ThreadTime(void);
void OS_ThreadInfoSet(OS_Thread_t *thread, uint32 index, void *info);
void *OS_ThreadInfoGet(OS_Thread_t *thread, uint32 index);
uint32 OS_ThreadPriorityGet(OS_Thread_t *thread);
void OS_ThreadPrioritySet(OS_Thread_t *thread, uint32 priority);
void OS_ThreadProcessId(OS_Thread_t *thread, uint32 processId, OS_Heap_t *heap);
void OS_ThreadTick(void *arg);
void OS_ThreadCpuLock(OS_Thread_t *thread, int cpuIndex);
/***************** Semaphore **************/
#define OS_SUCCESS 0
#define OS_ERROR -1
#define OS_WAIT_FOREVER -1
#define OS_NO_WAIT 0
typedef struct OS_Semaphore_s OS_Semaphore_t;
OS_Semaphore_t *OS_SemaphoreCreate(const char *name, uint32 count);
void OS_SemaphoreDelete(OS_Semaphore_t *semaphore);
int OS_SemaphorePend(OS_Semaphore_t *semaphore, int ticks); //tick ~= 10ms
void OS_SemaphorePost(OS_Semaphore_t *semaphore);
/***************** Mutex ******************/
typedef struct OS_Mutex_s OS_Mutex_t;
OS_Mutex_t *OS_MutexCreate(const char *name);
void OS_MutexDelete(OS_Mutex_t *semaphore);
void OS_MutexPend(OS_Mutex_t *semaphore);
void OS_MutexPost(OS_Mutex_t *semaphore);
/***************** MQueue *****************/
enum {
MESSAGE_TYPE_USER = 0,
MESSAGE_TYPE_TIMER = 5
};
typedef struct OS_MQueue_s OS_MQueue_t;
OS_MQueue_t *OS_MQueueCreate(const char *name,
int messageCount,
int messageBytes);
void OS_MQueueDelete(OS_MQueue_t *mQueue);
int OS_MQueueSend(OS_MQueue_t *mQueue, void *message);
int OS_MQueueGet(OS_MQueue_t *mQueue, void *message, int ticks);
/***************** Job ********************/
void OS_Job(void (*funcPtr)(), void *arg0, void *arg1, void *arg2);
/***************** Timer ******************/
typedef struct OS_Timer_s OS_Timer_t;
typedef void (*OS_TimerFuncPtr_t)(OS_Timer_t *timer, uint32 info);
OS_Timer_t *OS_TimerCreate(const char *name, OS_MQueue_t *mQueue, uint32 info);
void OS_TimerDelete(OS_Timer_t *timer);
void OS_TimerCallback(OS_Timer_t *timer, OS_TimerFuncPtr_t callback);
void OS_TimerStart(OS_Timer_t *timer, uint32 ticks, uint32 ticksRestart);
void OS_TimerStop(OS_Timer_t *timer);
/***************** ISR ********************/
#define STACK_EPC 88/4
void OS_InterruptServiceRoutine(uint32 status, uint32 *stack);
void OS_InterruptRegister(uint32 mask, OS_FuncPtr_t funcPtr);
uint32 OS_InterruptStatus(void);
uint32 OS_InterruptMaskSet(uint32 mask);
uint32 OS_InterruptMaskClear(uint32 mask);
/***************** Init ******************/
void OS_Init(uint32 *heapStorage, uint32 bytes);
void OS_Start(void);
void OS_Assert(void);
void OS_DebuggerInit(void);
void MainThread(void *Arg);
/***************** MMU ******************/
typedef struct {
const char *name;
OS_FuncPtr_t funcPtr;
void *arg;
uint32 priority;
uint32 stackSize;
uint32 heapSize;
uint32 processId;
OS_Semaphore_t *semaphoreDone;
uint8 *memory; //private
OS_Heap_t *heap; //private
OS_Thread_t *thread; //private
} OS_Process_t;
void OS_MMUInit(void);
void OS_MMUMemoryRegister(uint32 processId,
uint32 virtualAddress,
uint32 physicalAddress,
uint32 size,
uint32 writable);
OS_Process_t *OS_MMUProcessCreate(OS_Process_t *process);
void OS_MMUProcessDelete(OS_Process_t *process);
void OS_MMUUartPrintf();
void OS_MMUUartScanf();
void OS_MMUUartPrintfCritical();
/***************** UART ******************/
typedef uint8* (*PacketGetFunc_t)(void);
void UartInit(void);
void UartWrite(int ch);
uint8 UartRead(void);
void UartWriteData(uint8 *data, int length);
void UartReadData(uint8 *data, int length);
#ifndef NO_ELLIPSIS2
void UartPrintf(const char *format, ...);
void UartPrintfPoll(const char *format, ...);
void UartPrintfCritical(const char *format, ...);
void UartPrintfNull(const char *format, ...);
void UartScanf(const char *format, ...);
#endif
void UartPacketConfig(PacketGetFunc_t packetGetFunc,
int packetSize,
OS_MQueue_t *mQueue);
void UartPacketSend(uint8 *data, int bytes);
#ifdef WIN32
#define puts puts2
#define getch getch2
#define kbhit kbhit2
#endif
int puts(const char *string);
int getch(void);
int kbhit(void);
void LogWrite(int a);
void LogDump(void);
void Led(int mask, int value);
/***************** Keyboard **************/
#define KEYBOARD_RAW 0x100
#define KEYBOARD_E0 0x200
#define KEYBOARD_RELEASE 0x400
void KeyboardInit(void);
int KeyboardGetch(void);
/***************** Math ******************/
//IEEE single precision floating point math
#ifndef WIN32
#define FP_Neg __negsf2
#define FP_Add __addsf3
#define FP_Sub __subsf3
#define FP_Mult __mulsf3
#define FP_Div __divsf3
#define FP_ToLong __fixsfsi
#define FP_ToFloat __floatsisf
#define sqrt FP_Sqrt
#define cos FP_Cos
#define sin FP_Sin
#define atan FP_Atan
#define log FP_Log
#define exp FP_Exp
#endif
float FP_Neg(float a_fp);
float FP_Add(float a_fp, float b_fp);
float FP_Sub(float a_fp, float b_fp);
float FP_Mult(float a_fp, float b_fp);
float FP_Div(float a_fp, float b_fp);
long FP_ToLong(float a_fp);
float FP_ToFloat(long af);
int FP_Cmp(float a_fp, float b_fp);
float FP_Sqrt(float a);
float FP_Cos(float rad);
float FP_Sin(float rad);
float FP_Atan(float x);
float FP_Atan2(float y, float x);
float FP_Exp(float x);
float FP_Log(float x);
float FP_Pow(float x, float y);
/***************** Filesys ******************/
#ifdef INCLUDE_FILESYS
#define FILE OS_FILE
#define fopen OS_fopen
#define fclose OS_fclose
#define fread OS_fread
#define fwrite OS_fwrite
#define fseek OS_fseek
#endif
#define _FILESYS_
typedef struct OS_FILE_s OS_FILE;
OS_FILE *OS_fopen(char *name, char *mode);
void OS_fclose(OS_FILE *file);
int OS_fread(void *buffer, int size, int count, OS_FILE *file);
int OS_fwrite(void *buffer, int size, int count, OS_FILE *file);
int OS_fseek(OS_FILE *file, int offset, int mode);
int OS_fmkdir(char *name);
int OS_fdir(OS_FILE *dir, char name[64]);
void OS_fdelete(char *name);
int OS_flength(char *entry);
/***************** Flash ******************/
void FlashRead(uint16 *dst, uint32 byteOffset, int bytes);
void FlashWrite(uint16 *src, uint32 byteOffset, int bytes);
void FlashErase(uint32 byteOffset);
#endif //__RTOS_H__

522
plasma/kernel/rtos_test.c Normal file
View File

@@ -0,0 +1,522 @@
/*--------------------------------------------------------------------
* TITLE: Test Plasma Real Time Operating System
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
* DATE CREATED: 1/1/06
* FILENAME: rtos_test.c
* PROJECT: Plasma CPU core
* COPYRIGHT: Software placed into the public domain by the author.
* Software 'as is' without warranty. Author liable for nothing.
* DESCRIPTION:
* Test Plasma Real Time Operating System
*--------------------------------------------------------------------*/
#include "plasma.h"
#include "rtos.h"
#include "tcpip.h"
/* Including mmu.h will cause all OS calls to use SYSCALL */
//#include "mmu.h"
//#define DLL_SETUP
//#define DLL_CALL
//#include "dll.h"
#define SEMAPHORE_COUNT 50
#define TIMER_COUNT 10
extern void TestMathFull(void);
typedef struct {
OS_Thread_t *MyThread[TIMER_COUNT];
OS_Semaphore_t *MySemaphore[SEMAPHORE_COUNT];
OS_Mutex_t *MyMutex;
OS_Timer_t *MyTimer[TIMER_COUNT];
OS_MQueue_t *MyQueue[TIMER_COUNT];
int TimerDone;
} TestInfo_t;
int Global;
//******************************************************************
static void TestCLib(void)
{
char s1[80], s2[80], *ptr;
int rc, v1, v2, v3;
printf("TestCLib\n");
strcpy(s1, "Hello ");
memset(s2, 0, sizeof(s2));
strncpy(s2, "World wide", 5);
strcat(s1, s2);
strncat(s1, "!\nthing", 14);
printf("%s", s1);
rc = strcmp(s1, "Hello World!\n");
assert(rc == 0);
rc = strcmp(s1, "Hello WOrld!\n");
assert(rc > 0);
rc = strcmp(s1, "Hello world!\n");
assert(rc < 0);
rc = strncmp(s1, "Hellx", 4);
assert(rc == 0);
ptr = strstr(s1, "orl");
assert(ptr[0] = 'o');
rc = strlen(s1);
assert(rc == 13);
memcpy(s2, s1, rc+1);
rc = memcmp(s1, s2, 8);
assert(rc == 0);
s2[5] = 'z';
rc = memcmp(s1, s2, 8);
assert(rc != 0);
memset(s2, 0, 5);
memset(s2, 'a', 3);
rc = abs(-5);
itoa(1234, s1, 10);
itoa(0, s1, 10);
itoa(-1234, s1, 10);
itoa(0xabcd, s1, 16);
itoa(0x12ab, s1, 16);
sprintf(s1, "test c%c d%d 0x%x s%s End\n", 'C', 1234, 0xabcd, "String");
printf("%s", s1);
sprintf(s1, "test c%c d%6d 0x%6x s%8s End\n", 'C', 1234, 0xabcd, "String");
printf("%s", s1);
sscanf("1234 -1234 0xabcd text h", "%d %d %x %s", &v1, &v2, &v3, s1);
assert(v1 == 1234 && v2 == -1234 && v3 == 0xabcd);
assert(strcmp(s1, "text") == 0);
//UartScanf("%d %d", &v1, &v2);
//printf("v1 = %d v2 = %d\n", v1, v2);
printf("Done.\n");
}
//******************************************************************
static void TestHeap(void)
{
uint8 *ptrs[256], size[256], *ptr;
int i, j, k, value;
printf("TestHeap\n");
memset(ptrs, 0, sizeof(ptrs));
for(i = 0; i < 1000; ++i)
{
j = rand() & 255;
if(ptrs[j])
{
ptr = ptrs[j];
value = size[j];
for(k = 0; k < value; ++k)
{
if(ptr[k] != value)
printf("Error\n");
}
OS_HeapFree(ptrs[j]);
}
size[j] = (uint8)(rand() & 255);
ptrs[j] = OS_HeapMalloc(NULL, size[j]);
if(ptrs[j] == NULL)
printf("malloc NULL\n");
else
memset(ptrs[j], size[j], size[j]);
}
for(i = 0; i < 256; ++i)
{
if(ptrs[i])
OS_HeapFree(ptrs[i]);
}
printf("Done.\n");
}
//******************************************************************
static void MyThreadMain(void *arg)
{
OS_Thread_t *thread;
int priority;
thread = OS_ThreadSelf();
priority = OS_ThreadPriorityGet(thread);
OS_ThreadSleep(10);
printf("Arg=%d thread=0x%x info=0x%x priority=%d\n",
(uint32)arg, thread, OS_ThreadInfoGet(thread, 0), priority);
OS_ThreadExit();
}
static void TestThread(void)
{
OS_Thread_t *thread;
int i, priority;
printf("TestThread\n");
for(i = 0; i < 32; ++i)
{
priority = 50 + i;
thread = OS_ThreadCreate("MyThread", MyThreadMain, (uint32*)i, priority, 0);
OS_ThreadInfoSet(thread, 0, (void*)(0xabcd + i));
//printf("Created thread 0x%x\n", thread);
}
thread = OS_ThreadSelf();
priority = OS_ThreadPriorityGet(thread);
printf("Priority = %d\n", priority);
OS_ThreadPrioritySet(thread, 200);
printf("Priority = %d\n", OS_ThreadPriorityGet(thread));
OS_ThreadPrioritySet(thread, priority);
printf("Thread time = %d\n", OS_ThreadTime());
OS_ThreadSleep(100);
printf("Thread time = %d\n", OS_ThreadTime());
}
//******************************************************************
static void TestSemThread(void *arg)
{
int i;
TestInfo_t *info = (TestInfo_t*)arg;
for(i = 0; i < SEMAPHORE_COUNT/2; ++i)
{
printf("s");
OS_SemaphorePend(info->MySemaphore[i], OS_WAIT_FOREVER);
OS_SemaphorePost(info->MySemaphore[i + SEMAPHORE_COUNT/2]);
}
OS_ThreadExit();
}
static void TestSemaphore(void)
{
int i, rc;
TestInfo_t info;
printf("TestSemaphore\n");
for(i = 0; i < SEMAPHORE_COUNT; ++i)
{
info.MySemaphore[i] = OS_SemaphoreCreate("MySem", 0);
//printf("sem[%d]=0x%x\n", i, MySemaphore[i]);
}
OS_ThreadCreate("TestSem", TestSemThread, &info, 50, 0);
for(i = 0; i < SEMAPHORE_COUNT/2; ++i)
{
printf("S");
OS_SemaphorePost(info.MySemaphore[i]);
rc = OS_SemaphorePend(info.MySemaphore[i + SEMAPHORE_COUNT/2], 500);
assert(rc == 0);
}
printf(":");
rc = OS_SemaphorePend(info.MySemaphore[0], 10);
assert(rc != 0);
printf(":");
OS_SemaphorePend(info.MySemaphore[0], 100);
printf(":");
for(i = 0; i < SEMAPHORE_COUNT; ++i)
OS_SemaphoreDelete(info.MySemaphore[i]);
printf("\nDone.\n");
}
//******************************************************************
static void TestMutexThread(void *arg)
{
TestInfo_t *info = (TestInfo_t*)arg;
printf("Waiting for mutex\n");
OS_MutexPend(info->MyMutex);
printf("Have Mutex1\n");
OS_MutexPend(info->MyMutex);
printf("Have Mutex2\n");
OS_MutexPend(info->MyMutex);
printf("Have Mutex3\n");
OS_ThreadSleep(100);
OS_MutexPost(info->MyMutex);
OS_MutexPost(info->MyMutex);
OS_MutexPost(info->MyMutex);
OS_ThreadExit();
}
static void TestMutex(void)
{
TestInfo_t info;
printf("TestMutex\n");
info.MyMutex = OS_MutexCreate("MyMutex");
OS_MutexPend(info.MyMutex);
OS_MutexPend(info.MyMutex);
OS_MutexPend(info.MyMutex);
OS_ThreadSleep(100);
OS_ThreadCreate("TestMutex", TestMutexThread, &info, 50, 0);
OS_ThreadSleep(50);
OS_MutexPost(info.MyMutex);
OS_MutexPost(info.MyMutex);
OS_MutexPost(info.MyMutex);
printf("Try get mutex\n");
OS_MutexPend(info.MyMutex);
printf("Gotit\n");
OS_MutexDelete(info.MyMutex);
printf("Done.\n");
}
//******************************************************************
static void TestMQueue(void)
{
OS_MQueue_t *mqueue;
char data[16];
int i, rc;
printf("TestMQueue\n");
mqueue = OS_MQueueCreate("MyMQueue", 10, 16);
strcpy(data, "Test0");
for(i = 0; i < 16; ++i)
{
data[4] = (char)('0' + i);
OS_MQueueSend(mqueue, data);
}
for(i = 0; i < 16; ++i)
{
memset(data, 0, sizeof(data));
rc = OS_MQueueGet(mqueue, data, 20);
if(rc == 0)
printf("message=(%s)\n", data);
else
printf("timeout\n");
}
OS_MQueueDelete(mqueue);
printf("Done.\n");
}
//******************************************************************
static void TestTimerThread(void *arg)
{
int index;
uint32 data[4];
OS_Timer_t *timer;
TestInfo_t *info = (TestInfo_t*)arg;
//printf("TestTimerThread\n");
OS_ThreadSleep(1);
index = (int)OS_ThreadInfoGet(OS_ThreadSelf(), 0);
//printf("index=%d\n", index);
OS_MQueueGet(info->MyQueue[index], data, 1000);
timer = (OS_Timer_t*)data[1];
printf("%d ", data[2]);
OS_MQueueGet(info->MyQueue[index], data, 1000);
printf("%d ", data[2]);
++info->TimerDone;
OS_ThreadExit();
}
static void TestTimer(void)
{
int i;
TestInfo_t info;
printf("TestTimer\n");
info.TimerDone = 0;
for(i = 0; i < TIMER_COUNT; ++i)
{
info.MyQueue[i] = OS_MQueueCreate("MyQueue", 10, 16);
info.MyTimer[i] = OS_TimerCreate("MyTimer", info.MyQueue[i], i);
info.MyThread[i] = OS_ThreadCreate("TimerTest", TestTimerThread, &info, 50, 0);
OS_ThreadInfoSet(info.MyThread[i], 0, (void*)i);
OS_TimerStart(info.MyTimer[i], 10+i*2, 220+i);
}
while(info.TimerDone < TIMER_COUNT)
OS_ThreadSleep(10);
for(i = 0; i < TIMER_COUNT; ++i)
{
OS_MQueueDelete(info.MyQueue[i]);
OS_TimerDelete(info.MyTimer[i]);
}
printf("Done.\n");
}
//******************************************************************
#if 1
void TestMath(void)
{
int i;
float a, b, sum, diff, mult, div;
uint32 compare;
//Check add subtract multiply and divide
for(i = -4; i < 4; ++i)
{
a = (float)(i * 10 + (float)63.2);
b = (float)(-i * 5 + (float)3.5);
sum = a + b;
diff = a - b;
mult = a * b;
div = a / b;
printf("a=%dE-3 b=%dE-3 sum=%dE-3 diff=%dE-3 mult=%dE-3 div=%dE-3\n",
(int)(a*(float)1000), (int)(b*(float)1000),
(int)(sum*(float)1000), (int)(diff*(float)1000),
(int)(mult*(float)1000), (int)(div*(float)1000));
}
//Comparisons
b = (float)2.0;
compare = 0;
for(i = 1; i < 4; ++i)
{
a = (float)i;
compare = (compare << 1) | (a == b);
compare = (compare << 1) | (a != b);
compare = (compare << 1) | (a < b);
compare = (compare << 1) | (a <= b);
compare = (compare << 1) | (a > b);
compare = (compare << 1) | (a >= b);
}
printf("Compare = %8x %s\n", compare,
compare==0x1c953 ? "OK" : "ERROR");
//Cosine
for(a = (float)0.0; a <= (float)(3.1415); a += (float)(3.1415/16.0))
{
b = FP_Cos(a);
printf("cos(%4dE-3) = %4dE-3\n",
(int)(a*(float)1000.0), (int)(b*(float)1000.0));
}
}
#endif
//******************************************************************
#ifndef WIN32
static void MySyscall(void *arg)
{
uint32 *stack = arg;
stack[STACK_EPC] += 4; //skip over SYSCALL
printf("Inside MySyscall %d\n", stack[28/4]);
}
void TestSyscall(void)
{
OS_InterruptRegister((uint32)(1<<31), MySyscall);
OS_Syscall(57);
OS_ThreadSleep(1);
printf("Done\n");
}
#endif
#ifdef __MMU_ENUM_H__
void TestProcess(void)
{
OS_Process_t *process;
process = (OS_Process_t*)OS_HeapMalloc(NULL, sizeof(OS_Process_t));
process->name = "test";
process->funcPtr = MainThread;
process->arg = NULL;
process->priority = 200;
process->stackSize = 1024*32;
process->heapSize = 1024*128;
process->processId = 1;
process->semaphoreDone = OS_SemaphoreCreate("processDone", 0);
printf("Creating process\n");
OS_MMUProcessCreate(process);
OS_SemaphorePend(process->semaphoreDone, OS_WAIT_FOREVER);
printf("Process done\n");
OS_MMUProcessDelete(process);
}
#endif
//******************************************************************
void MMUTest(void);
void HtmlThread(void *arg);
void ConsoleInit(void);
void exit(int);
uint8 macAddress[] = {0x00, 0x10, 0xdd, 0xce, 0x15, 0xd4};
void MainThread(void *Arg)
{
int ch, i, display=1;
(void)Arg;
#ifdef __MMU_ENUM_H__
OS_MMUInit();
#endif
#ifdef INCLUDE_ETH
EthernetInit(macAddress);
IPInit(EthernetTransmit, macAddress, "plasma");
HtmlInit(1);
#endif
#ifdef INCLUDE_HTML
IPInit(NULL, macAddress, "plasma");
HtmlInit(1);
#endif
#ifdef INCLUDE_CONSOLE
ConsoleInit();
#endif
for(;;)
{
if(display)
{
printf("\n");
printf("1 CLib\n");
printf("2 Heap\n");
printf("3 Thread\n");
printf("4 Semaphore\n");
printf("5 Mutex\n");
printf("6 MQueue\n");
printf("7 Timer\n");
printf("8 Math\n");
printf("9 Syscall\n");
#ifdef __MMU_ENUM_H__
printf("p MMU Process\n");
#endif
}
printf("> ");
display = 1;
ch = UartRead();
printf("%c\n", ch);
switch(ch)
{
#ifdef WIN32
case '0': exit(0);
#endif
case '1': TestCLib(); break;
case '2': TestHeap(); break;
case '3': TestThread(); break;
case '4': TestSemaphore(); break;
case '5': TestMutex(); break;
case '6': TestMQueue(); break;
case '7': TestTimer(); break;
case '8': TestMath(); break;
#ifndef WIN32
case '9': TestSyscall(); break;
#endif
#ifdef __MMU_ENUM_H__
case 'p': TestProcess(); break;
#endif
#ifdef WIN32
case 'm': TestMathFull(); break;
#endif
case 'g': printf("Global=%d\n", ++Global); break;
default:
printf("E");
display = 0;
for(i = 0; i < 30; ++i)
{
while(kbhit())
ch = UartRead();
OS_ThreadSleep(1);
}
break;
}
}
}

1679
plasma/kernel/tcpip.c Normal file

File diff suppressed because it is too large Load Diff

131
plasma/kernel/tcpip.h Normal file
View File

@@ -0,0 +1,131 @@
/*--------------------------------------------------------------------
* TITLE: Plasma TCP/IP Protocol Stack
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
* DATE CREATED: 4/22/06
* FILENAME: tcpip.h
* PROJECT: Plasma CPU core
* COPYRIGHT: Software placed into the public domain by the author.
* Software 'as is' without warranty. Author liable for nothing.
* DESCRIPTION:
* Plasma TCP/IP Protocol Stack
*--------------------------------------------------------------------*/
#ifndef __TCPIP_H__
#define __TCPIP_H__
#define PACKET_SIZE 600
#define FRAME_COUNT 100
#define FRAME_COUNT_SYNC 50
#define FRAME_COUNT_SEND 10
#define FRAME_COUNT_RCV 5
#define RETRANSMIT_TIME 110
#define SOCKET_TIMEOUT 12
#define SEND_WINDOW 7000
#define RECEIVE_WINDOW 5120
typedef enum IPMode_e {
IP_MODE_UDP,
IP_MODE_TCP,
IP_MODE_PING
} IPMode_e;
typedef enum IPState_e {
IP_LISTEN,
IP_PING,
IP_UDP,
IP_SYN,
IP_TCP,
IP_FIN_CLIENT,
IP_FIN_SERVER,
IP_CLOSED
} IPState_e;
typedef void (*IPFuncPtr)();
typedef struct IPFrame {
uint8 packet[PACKET_SIZE];
struct IPFrame *next, *prev;
struct IPSocket *socket;
uint32 seqEnd;
uint16 length;
short timeout;
uint8 state, retryCnt;
} IPFrame;
typedef struct IPSocket {
struct IPSocket *next, *prev;
IPState_e state;
uint32 seq;
uint32 seqReceived;
uint32 seqWindow;
uint32 ack;
uint32 ackProcessed;
uint32 timeout;
uint32 timeoutReset;
int resentDone;
int dontFlush;
uint8 headerSend[38];
uint8 headerRcv[38];
struct IPFrame *frameReadHead;
struct IPFrame *frameReadTail;
int readOffset;
struct IPFrame *frameSend;
int sendOffset;
void *fileOut;
void *fileIn;
IPFuncPtr funcPtr;
IPFuncPtr userFunc;
void *userPtr;
void *userPtr2;
uint32 userData;
uint32 userData2;
} IPSocket;
//ethernet.c
void EthernetSendPacket(const unsigned char *packet, int length); //Windows
void EthernetInit(unsigned char MacAddress[6]);
int EthernetReceive(unsigned char *buffer, int length);
void EthernetTransmit(unsigned char *buffer, int length);
//tcpip.c
void IPInit(IPFuncPtr frameSendFunction, uint8 macAddress[6], char name[6]);
IPFrame *IPFrameGet(int freeCount);
int IPProcessEthernetPacket(IPFrame *frameIn, int length);
void IPTick(void);
IPSocket *IPOpen(IPMode_e mode, uint32 ipAddress, uint32 port, IPFuncPtr funcPtr);
void IPWriteFlush(IPSocket *socket);
uint32 IPWrite(IPSocket *socket, const uint8 *buf, uint32 length);
uint32 IPRead(IPSocket *socket, uint8 *buf, uint32 length);
void IPClose(IPSocket *socket);
#ifdef IPPRINTF
void IPPrintf(IPSocket *socket, char *message, int arg0, int arg1, int arg2, int arg3);
#else
void IPPrintf(IPSocket *socket, char *message, ...);
#endif
void IPResolve(char *name, IPFuncPtr resolvedFunc, void *arg);
uint32 IPAddressSelf(void);
//http.c
#define HTML_LENGTH_CALLBACK -2
#define HTML_LENGTH_LIST_END -1
typedef struct PageEntry_s {
const char *name;
int length;
const char *page;
} PageEntry_t;
void HttpInit(const PageEntry_t *Pages, int UseFiles);
//html.c
void HtmlInit(int UseFiles);
//netutil.c
void FtpdInit(int UseFiles);
IPSocket *FtpTransfer(uint32 ip, char *user, char *passwd,
char *filename, uint8 *buf, int size,
int send, void (*callback)(uint8 *data, int size));
void TftpdInit(void);
IPSocket *TftpTransfer(uint32 ip, char *filename, uint8 *buffer, int size,
void (*callback)(uint8 *data, int bytes));
void ConsoleInit(void);
void *IPNameValue(const char *name, void *value);
#endif //__TCPIP_H__

549
plasma/kernel/uart.c Normal file
View File

@@ -0,0 +1,549 @@
/*--------------------------------------------------------------------
* TITLE: Plasma Uart Driver
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
* DATE CREATED: 12/31/05
* FILENAME: uart.c
* PROJECT: Plasma CPU core
* COPYRIGHT: Software placed into the public domain by the author.
* Software 'as is' without warranty. Author liable for nothing.
* DESCRIPTION:
* Plasma Uart Driver
*--------------------------------------------------------------------*/
#define NO_ELLIPSIS2
#include "plasma.h"
#include "rtos.h"
#ifndef NO_PACKETS
#define SUPPORT_DATA_PACKETS
#endif
#define BUFFER_WRITE_SIZE 128
#define BUFFER_READ_SIZE 128
#define BUFFER_PRINTF_SIZE 1024
#undef UartPrintf
void UartPrintfCritical(const char *format,
int arg0, int arg1, int arg2, int arg3,
int arg4, int arg5, int arg6, int arg7);
typedef struct Buffer_s {
uint8 *data;
int size;
volatile int read, write;
volatile int pendingRead, pendingWrite;
OS_Semaphore_t *semaphoreRead, *semaphoreWrite;
} Buffer_t;
static Buffer_t *WriteBuffer, *ReadBuffer;
static OS_Semaphore_t *SemaphoreUart;
static char PrintfString[BUFFER_PRINTF_SIZE]; //Used in UartPrintf
#ifdef SUPPORT_DATA_PACKETS
//For packet processing [0xff lengthMSB lengthLSB checksum data]
static PacketGetFunc_t UartPacketGet;
static uint8 *PacketCurrent;
static uint32 UartPacketSize;
static uint32 UartPacketChecksum, Checksum;
static OS_MQueue_t *UartPacketMQueue;
static uint32 PacketBytes, PacketLength;
static uint32 UartPacketOutLength, UartPacketOutByte;
int CountOk, CountError;
#endif
static uint8 *UartPacketOut;
/******************************************/
Buffer_t *BufferCreate(int size)
{
Buffer_t *buffer;
buffer = (Buffer_t*)OS_HeapMalloc(NULL, sizeof(Buffer_t) + size);
if(buffer == NULL)
return NULL;
buffer->data = (uint8*)(buffer + 1);
buffer->read = 0;
buffer->write = 0;
buffer->size = size;
buffer->pendingRead = 0;
buffer->pendingWrite = 0;
buffer->semaphoreRead = OS_SemaphoreCreate("BufferRead", 0);
buffer->semaphoreWrite = OS_SemaphoreCreate("BufferWrite", 0);
return buffer;
}
void BufferWrite(Buffer_t *buffer, int value, int pend)
{
int writeNext;
writeNext = buffer->write + 1;
if(writeNext >= buffer->size)
writeNext = 0;
//Check if room for value
if(writeNext == buffer->read)
{
if(pend == 0)
return;
++buffer->pendingWrite;
OS_SemaphorePend(buffer->semaphoreWrite, OS_WAIT_FOREVER);
}
buffer->data[buffer->write] = (uint8)value;
buffer->write = writeNext;
if(buffer->pendingRead)
{
--buffer->pendingRead;
OS_SemaphorePost(buffer->semaphoreRead);
}
}
int BufferRead(Buffer_t *buffer, int pend)
{
int value;
//Check if empty buffer
if(buffer->read == buffer->write)
{
if(pend == 0)
return 0;
++buffer->pendingRead;
OS_SemaphorePend(buffer->semaphoreRead, OS_WAIT_FOREVER);
}
value = buffer->data[buffer->read];
if(++buffer->read >= buffer->size)
buffer->read = 0;
if(buffer->pendingWrite)
{
--buffer->pendingWrite;
OS_SemaphorePost(buffer->semaphoreWrite);
}
return value;
}
/******************************************/
#ifdef SUPPORT_DATA_PACKETS
static void UartPacketRead(uint32 value)
{
uint32 message[4];
if(PacketBytes == 0 && value == 0xff)
{
++PacketBytes;
}
else if(PacketBytes == 1)
{
++PacketBytes;
PacketLength = value << 8;
}
else if(PacketBytes == 2)
{
++PacketBytes;
PacketLength |= value;
if(PacketLength <= UartPacketSize)
{
if(PacketCurrent == NULL)
PacketCurrent = UartPacketGet();
}
else
{
PacketBytes = 0;
}
}
else if(PacketBytes == 3)
{
++PacketBytes;
UartPacketChecksum = value;
Checksum = 0;
}
else if(PacketBytes >= 4)
{
if(PacketCurrent)
PacketCurrent[PacketBytes - 4] = (uint8)value;
Checksum += value;
++PacketBytes;
if(PacketBytes - 4 >= PacketLength)
{
if((uint8)Checksum == UartPacketChecksum)
{
//Notify thread that a packet has been received
++CountOk;
message[0] = 0;
message[1] = (uint32)PacketCurrent;
message[2] = PacketLength;
if(PacketCurrent)
OS_MQueueSend(UartPacketMQueue, message);
PacketCurrent = NULL;
}
else
{
++CountError;
//printf("E");
}
PacketBytes = 0;
}
}
}
static int UartPacketWrite(void)
{
int value=0, i;
uint32 message[4];
if(UartPacketOut)
{
if(UartPacketOutByte == 0)
{
value = 0xff;
++UartPacketOutByte;
}
else if(UartPacketOutByte == 1)
{
value = UartPacketOutLength >> 8;
++UartPacketOutByte;
}
else if(UartPacketOutByte == 2)
{
value = (uint8)UartPacketOutLength;
++UartPacketOutByte;
}
else if(UartPacketOutByte == 3)
{
value = 0;
for(i = 0; i < (int)UartPacketOutLength; ++i)
value += UartPacketOut[i];
value = (uint8)value;
++UartPacketOutByte;
}
else
{
value = UartPacketOut[UartPacketOutByte - 4];
++UartPacketOutByte;
if(UartPacketOutByte - 4 >= UartPacketOutLength)
{
//Notify thread that a packet has been sent
message[0] = 1;
message[1] = (uint32)UartPacketOut;
UartPacketOut = 0;
OS_MQueueSend(UartPacketMQueue, message);
}
}
}
return value;
}
#endif
static void UartInterrupt(void *arg)
{
uint32 status, value, count=0;
(void)arg;
status = OS_InterruptStatus();
while(status & IRQ_UART_READ_AVAILABLE)
{
value = MemoryRead(UART_READ);
#ifdef SUPPORT_DATA_PACKETS
if(UartPacketGet && (value == 0xff || PacketBytes))
UartPacketRead(value);
else
#endif
BufferWrite(ReadBuffer, value, 0);
status = OS_InterruptStatus();
if(++count >= 16)
break;
}
while(status & IRQ_UART_WRITE_AVAILABLE)
{
#ifdef SUPPORT_DATA_PACKETS
if(UartPacketOut)
{
value = UartPacketWrite();
MemoryWrite(UART_WRITE, value);
} else
#endif
if(WriteBuffer->read != WriteBuffer->write)
{
value = BufferRead(WriteBuffer, 0);
MemoryWrite(UART_WRITE, value);
}
else
{
OS_InterruptMaskClear(IRQ_UART_WRITE_AVAILABLE);
break;
}
status = OS_InterruptStatus();
}
}
void UartInit(void)
{
uint32 mask;
SemaphoreUart = OS_SemaphoreCreate("Uart", 1);
WriteBuffer = BufferCreate(BUFFER_WRITE_SIZE);
ReadBuffer = BufferCreate(BUFFER_READ_SIZE);
mask = IRQ_UART_READ_AVAILABLE | IRQ_UART_WRITE_AVAILABLE;
OS_InterruptRegister(mask, UartInterrupt);
OS_InterruptMaskSet(IRQ_UART_READ_AVAILABLE);
}
void UartWrite(int ch)
{
BufferWrite(WriteBuffer, ch, 1);
OS_InterruptMaskSet(IRQ_UART_WRITE_AVAILABLE);
}
uint8 UartRead(void)
{
return (uint8)BufferRead(ReadBuffer, 1);
}
void UartWriteData(uint8 *data, int length)
{
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
while(length--)
UartWrite(*data++);
OS_SemaphorePost(SemaphoreUart);
}
void UartReadData(uint8 *data, int length)
{
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
while(length--)
*data++ = UartRead();
OS_SemaphorePost(SemaphoreUart);
}
void UartPrintf(const char *format,
int arg0, int arg1, int arg2, int arg3,
int arg4, int arg5, int arg6, int arg7)
{
uint8 *ptr;
#if 0
//Check for string "!m#~" to mask print statement
static char moduleLevel[26];
if(format[0] == '!' && format[3] == '~')
{
int level = format[2] - '5';
if('a' <= format[1] && format[1] <= 'z')
{
if(level < moduleLevel[format[1] - 'a'])
return;
}
else if('A' <= format[1] && format[1] <= 'Z')
moduleLevel[format[1] - 'A'] = (char)level;
format += 4;
}
#endif
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
arg4, arg5, arg6, arg7);
ptr = (uint8*)PrintfString;
while(*ptr)
{
if(*ptr == '\n')
UartWrite('\r');
#ifdef SUPPORT_DATA_PACKETS
if(*ptr == 0xff)
*ptr = '@';
#endif
UartWrite(*ptr++);
}
OS_SemaphorePost(SemaphoreUart);
}
void UartPrintfPoll(const char *format,
int arg0, int arg1, int arg2, int arg3,
int arg4, int arg5, int arg6, int arg7)
{
uint8 *ptr;
uint32 state;
if(SemaphoreUart)
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
arg4, arg5, arg6, arg7);
ptr = (uint8*)PrintfString;
while(*ptr)
{
while((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) == 0)
;
state = OS_CriticalBegin();
if((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) &&
UartPacketOut == NULL)
{
MemoryWrite(UART_WRITE, *ptr++);
}
OS_CriticalEnd(state);
}
if(SemaphoreUart)
OS_SemaphorePost(SemaphoreUart);
}
void UartPrintfCritical(const char *format,
int arg0, int arg1, int arg2, int arg3,
int arg4, int arg5, int arg6, int arg7)
{
uint8 *ptr;
uint32 state;
state = OS_CriticalBegin();
sprintf(PrintfString, format, arg0, arg1, arg2, arg3,
arg4, arg5, arg6, arg7);
ptr = (uint8*)PrintfString;
while(*ptr)
{
while((MemoryRead(IRQ_STATUS) & IRQ_UART_WRITE_AVAILABLE) == 0)
;
MemoryWrite(UART_WRITE, *ptr++);
#ifdef SUPPORT_DATA_PACKETS
if(UartPacketOut && UartPacketOutByte - 4 < UartPacketOutLength)
{
++UartPacketOutByte;
--ptr;
}
#endif
}
memset(PrintfString, 0, sizeof(PrintfString));
OS_CriticalEnd(state);
}
void UartPrintfNull(void)
{
}
void UartScanf(const char *format,
int arg0, int arg1, int arg2, int arg3,
int arg4, int arg5, int arg6, int arg7)
{
int index = 0, ch;
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
for(;;)
{
ch = UartRead();
if(ch != '\b' || index)
UartWrite(ch);
if(ch == '\n' || ch == '\r')
break;
else if(ch == '\b')
{
if(index)
{
UartWrite(' ');
UartWrite(ch);
--index;
}
}
else if(index < sizeof(PrintfString))
PrintfString[index++] = (uint8)ch;
}
UartWrite('\n');
PrintfString[index] = 0;
sscanf(PrintfString, format, arg0, arg1, arg2, arg3,
arg4, arg5, arg6, arg7);
OS_SemaphorePost(SemaphoreUart);
}
#ifdef SUPPORT_DATA_PACKETS
void UartPacketConfig(PacketGetFunc_t PacketGetFunc,
int PacketSize,
OS_MQueue_t *mQueue)
{
UartPacketGet = PacketGetFunc;
UartPacketSize = PacketSize;
UartPacketMQueue = mQueue;
}
void UartPacketSend(uint8 *data, int bytes)
{
UartPacketOutByte = 0;
UartPacketOutLength = bytes;
UartPacketOut = data;
OS_InterruptMaskSet(IRQ_UART_WRITE_AVAILABLE);
}
#else
void UartPacketConfig(PacketGetFunc_t PacketGetFunc,
int PacketSize,
OS_MQueue_t *mQueue)
{ (void)PacketGetFunc; (void)PacketSize; (void)mQueue; }
void UartPacketSend(uint8 *data, int bytes)
{ (void)data; (void)bytes; }
#endif
void Led(int mask, int value)
{
mask &= 0xff;
MemoryWrite(GPIO0_CLEAR, mask); //clear
MemoryWrite(GPIO0_OUT, value & mask); //set LEDs
}
/******************************************/
int puts(const char *string)
{
uint8 *ptr;
OS_SemaphorePend(SemaphoreUart, OS_WAIT_FOREVER);
ptr = (uint8*)string;
while(*ptr)
{
if(*ptr == '\n')
UartWrite('\r');
UartWrite(*ptr++);
}
OS_SemaphorePost(SemaphoreUart);
return 0;
}
int getch(void)
{
return BufferRead(ReadBuffer, 1);
}
int kbhit(void)
{
return ReadBuffer->read != ReadBuffer->write;
}
/******************************************/
#if 0
int LogArray[100], LogIndex;
void LogWrite(int a)
{
if(LogIndex < sizeof(LogArray)/4)
LogArray[LogIndex++] = a;
}
void LogDump(void)
{
int i;
for(i = 0; i < LogIndex; ++i)
{
if(LogArray[i] > 0xfff)
UartPrintfCritical("\n", 0,0,0,0,0,0,0,0);
UartPrintfCritical("0x%x ", LogArray[i], 0,0,0,0,0,0,0);
}
LogIndex = 0;
}
#endif