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:
537
plasma/kernel/dll.h
Normal file
537
plasma/kernel/dll.h
Normal 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
38
plasma/kernel/dlltest.c
Normal 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
408
plasma/kernel/ethernet.c
Normal 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
767
plasma/kernel/filesys.c
Normal 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
52
plasma/kernel/flash.c
Normal 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
230
plasma/kernel/http.c
Normal 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
666
plasma/kernel/libc.c
Normal 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
192
plasma/kernel/makefile
Normal 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
692
plasma/kernel/math.c
Normal 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
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
71
plasma/kernel/os_stubs.c
Normal 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
1467
plasma/kernel/rtos.c
Normal file
File diff suppressed because it is too large
Load Diff
377
plasma/kernel/rtos.h
Normal file
377
plasma/kernel/rtos.h
Normal 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
522
plasma/kernel/rtos_test.c
Normal 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
1679
plasma/kernel/tcpip.c
Normal file
File diff suppressed because it is too large
Load Diff
131
plasma/kernel/tcpip.h
Normal file
131
plasma/kernel/tcpip.h
Normal 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
549
plasma/kernel/uart.c
Normal 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
|
||||
|
||||
Reference in New Issue
Block a user