diff --git a/bsp/simulator/SConstruct b/bsp/simulator/SConstruct old mode 100644 new mode 100755 index 0bd7e05ec..4dd5342cc --- a/bsp/simulator/SConstruct +++ b/bsp/simulator/SConstruct @@ -18,38 +18,44 @@ else: sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] from building import * -TARGET = 'rtthread-win32.' + rtconfig.TARGET_EXT env = Environment() Export('RTT_ROOT') Export('rtconfig') -libs = Split(''' -winmm -gdi32 -winspool -comdlg32 -advapi32 -shell32 -ole32 -oleaut32 -uuid -odbc32 -odbccp32 -''') -definitions = Split(''' -WIN32 -_DEBUG -_CONSOLE -MSVC -_TIME_T_DEFINED -''') +if rtconfig.PLATFORM == 'cl': + TARGET = 'rtthread-win32.' + rtconfig.TARGET_EXT + + libs = Split(''' + winmm + gdi32 + winspool + comdlg32 + advapi32 + shell32 + ole32 + oleaut32 + uuid + odbc32 + odbccp32 + ''') + definitions = Split(''' + WIN32 + _DEBUG + _CONSOLE + MSVC + _TIME_T_DEFINED + ''') + env.Append(CCFLAGS=rtconfig.CFLAGS) + env.Append(LINKFLAGS=rtconfig.LFLAGS) + env['LIBS']=libs + env['CPPDEFINES']=definitions +else: + TARGET = 'rtthread' + env.Append(CCFLAGS=rtconfig.CFLAGS) + env.Append(LINKFLAGS=rtconfig.LFLAGS) -env.Append(CCFLAGS=rtconfig.CFLAGS) -env.Append(LINKFLAGS=rtconfig.LFLAGS) -env['LIBS']=libs -env['CPPDEFINES']=definitions # prepare building environment diff --git a/bsp/simulator/applications/SConscript b/bsp/simulator/applications/SConscript index 4ccb17720..828b49f77 100644 --- a/bsp/simulator/applications/SConscript +++ b/bsp/simulator/applications/SConscript @@ -1,7 +1,11 @@ from building import * -cwd = GetCurrentDir() +cwd = GetCurrentDir() src = Glob('*.c') + +# remove no need file. +if GetDepend('RT_USING_DFS_WINSHAREDIR') == False: + SrcRemove(src, 'dfs_win32.c') CPPPATH = [cwd, str(Dir('#'))] group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) diff --git a/bsp/simulator/applications/application.c b/bsp/simulator/applications/application.c old mode 100644 new mode 100755 index abd582c3c..86db4113a --- a/bsp/simulator/applications/application.c +++ b/bsp/simulator/applications/application.c @@ -18,6 +18,7 @@ #include + void rt_init_thread_entry(void *parameter) { #ifdef RT_USING_LWIP @@ -49,7 +50,11 @@ void rt_init_thread_entry(void *parameter) #ifdef RT_USING_DFS_ELMFAT /* mount sd card fatfs as root directory */ +#ifdef _WIN32 if (dfs_mount("sd0", "/disk/sd", "elm", 0, 0) == 0) +#else + if (dfs_mount("sd0", "/", "elm", 0, 0) == 0) +#endif rt_kprintf("fatfs initialized!\n"); else rt_kprintf("fatfs initialization failed!\n"); @@ -73,31 +78,19 @@ void rt_init_thread_entry(void *parameter) } #endif - -#if 0 - { - extern void application_init(void); - rt_thread_delay(RT_TICK_PER_SECOND); - application_init(); - } -#endif - -#if defined(RT_USING_RTGUI) - rt_thread_delay(3000); - snake_main(); -#endif } static void rt_test_thread_entry(void *parameter) { int i; - for (i = 0; i < 10; i++) + for (i = 0; i < 5; i++) { rt_kprintf("hello, world\n"); - rt_thread_delay(100); + rt_thread_delay(RT_TICK_PER_SECOND); } } + int rt_application_init() { rt_thread_t tid; @@ -118,5 +111,4 @@ int rt_application_init() return 0; } - /*@}*/ diff --git a/bsp/simulator/drivers/board.c b/bsp/simulator/drivers/board.c old mode 100644 new mode 100755 index c6320d27b..dc24d39e2 --- a/bsp/simulator/drivers/board.c +++ b/bsp/simulator/drivers/board.c @@ -16,7 +16,6 @@ #include #include "board.h" #include -#include /** * @addtogroup simulator on win32 @@ -30,29 +29,56 @@ rt_uint8_t *rt_hw_sram_init(void) if (heap == RT_NULL) { rt_kprintf("there is no memory in pc."); +#ifdef _WIN32 _exit(1); +#else + exit(1); +#endif } return heap; } +#ifdef _WIN32 +#include +#endif + void rt_hw_win32_low_cpu(void) { +#ifdef _WIN32 + /* in windows */ Sleep(1000); +#else + /* in linux */ + sleep(1); +#endif } -#if defined(RT_USING_FINSH) - +#ifdef _WIN32 #ifndef _CRT_TERMINATE_DEFINED #define _CRT_TERMINATE_DEFINED _CRTIMP __declspec(noreturn) void __cdecl exit(__in int _Code); _CRTIMP __declspec(noreturn) void __cdecl _exit(__in int _Code); _CRTIMP void __cdecl abort(void); #endif +#endif +#if defined(RT_USING_FINSH) #include void rt_hw_exit(void) { rt_kprintf("RT-Thread, bye\n"); +#if !defined(_WIN32) && defined(__GNUC__) + /* * + * getchar reads key from buffer, while finsh need an non-buffer getchar + * in windows, getch is such an function, in linux, we had to change + * the behaviour of terminal to get an non-buffer getchar. + * in usart_sim.c, set_stty is called to do this work + * */ + { + extern void restore_stty(void); + restore_stty(); + } +#endif exit(0); } FINSH_FUNCTION_EXPORT_ALIAS(rt_hw_exit, exit, exit rt - thread); @@ -66,8 +92,11 @@ void rt_hw_board_init() /* init system memory */ heap = rt_hw_sram_init(); -#if defined(RT_USING_CONSOLE) +//#if defined(RT_USING_USART) rt_hw_usart_init(); +//#endif + +#if defined(RT_USING_CONSOLE) rt_hw_serial_init(); rt_console_set_device(RT_CONSOLE_DEVICE_NAME); #endif diff --git a/bsp/simulator/drivers/sd_sim.c b/bsp/simulator/drivers/sd_sim.c old mode 100644 new mode 100755 index 7c9844bae..1f39843d3 --- a/bsp/simulator/drivers/sd_sim.c +++ b/bsp/simulator/drivers/sd_sim.c @@ -1,7 +1,7 @@ #include #include -#include -#include +//#include +//#include #include // #define SD_TRACE rt_kprintf diff --git a/bsp/simulator/drivers/sdl_fb.c b/bsp/simulator/drivers/sdl_fb.c old mode 100644 new mode 100755 index 790797f2a..752a6fb93 --- a/bsp/simulator/drivers/sdl_fb.c +++ b/bsp/simulator/drivers/sdl_fb.c @@ -1,6 +1,10 @@ #include +#ifdef _WIN32 #include +#else +#include +#endif #include #include @@ -104,7 +108,7 @@ static void sdlfb_hw_init(void) //_putenv("SDL_VIDEODRIVER=windib"); //if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO) < 0) - if (SDL_Init(SDL_INIT_EVERYTHING) < 0) + if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); exit(1); @@ -132,16 +136,24 @@ static void sdlfb_hw_init(void) sdllock = rt_mutex_create("fb", RT_IPC_FLAG_FIFO); } +#ifdef _WIN32 #include #include +#else +#include +#endif + #include -#include #include #include #include #include +#ifdef _WIN32 static DWORD WINAPI sdl_loop(LPVOID lpParam) +#else +static void *sdl_loop(void *lpParam) +#endif { int quit = 0; SDL_Event event; @@ -284,6 +296,7 @@ static DWORD WINAPI sdl_loop(LPVOID lpParam) /* start sdl thread */ void rt_hw_sdl_start(void) { +#ifdef _WIN32 HANDLE thread; DWORD thread_id; @@ -301,4 +314,15 @@ void rt_hw_sdl_start(void) return; } ResumeThread(thread); +#else + /* Linux */ + pthread_t pid; + int res; + res = pthread_create(&pid, NULL, &sdl_loop, NULL); + if (res) + { + printf("pthread create sdl thread faild, <%d>\n", res); + exit(EXIT_FAILURE); + } +#endif } diff --git a/bsp/simulator/drivers/serial.c b/bsp/simulator/drivers/serial.c old mode 100644 new mode 100755 index 5a18d98bd..87de4d049 --- a/bsp/simulator/drivers/serial.c +++ b/bsp/simulator/drivers/serial.c @@ -13,8 +13,12 @@ #include "serial.h" #include struct rt_device serial_device; -extern struct serial_int_rx serial_rx; +//extern struct serial_int_rx serial_rx; +struct serial_int_rx serial_rx; + +#if 0 static FILE *fp = RT_NULL; +#endif /*@{*/ @@ -109,13 +113,16 @@ static rt_size_t rt_serial_write(rt_device_t dev, rt_off_t pos, const void *buff #if _DEBUG_SERIAL==1 printf("in rt_serial_write()\n"); #endif +#if 0 if (fp == NULL) fp = fopen("log.txt", "wb+"); if (fp != NULL) fwrite(buffer, size, 1, fp); +#endif printf("%s", (char *)buffer); + fflush(stdout); return size; } diff --git a/bsp/simulator/drivers/usart_sim.c b/bsp/simulator/drivers/usart_sim.c old mode 100644 new mode 100755 index efc04614c..2cbb1ed34 --- a/bsp/simulator/drivers/usart_sim.c +++ b/bsp/simulator/drivers/usart_sim.c @@ -1,15 +1,19 @@ #include #include + +#ifdef _WIN32 #include #include -#include #include +#endif +#include #include "serial.h" struct serial_int_rx serial_rx; extern struct rt_device serial_device; +#ifdef _WIN32 /* * Handler for OSKey Thread */ @@ -19,7 +23,6 @@ static DWORD OSKey_ThreadID; static DWORD WINAPI ThreadforKeyGet(LPVOID lpParam); void rt_hw_usart_init(void) { - /* * create serial thread that receive key input from keyboard */ @@ -46,9 +49,31 @@ void rt_hw_usart_init(void) * Start OS get key Thread */ ResumeThread(OSKey_Thread); - } +#else /* POSIX version */ + +#include +#include +#include +#include +#include /* for tcxxxattr, ECHO, etc */ +#include /* for STDIN_FILENO */ + + +static void * ThreadforKeyGet(void * lpParam); +static pthread_t OSKey_Thread; +void rt_hw_usart_init(void) +{ + int res; + res = pthread_create(&OSKey_Thread, NULL, &ThreadforKeyGet, NULL); + if (res) + { + printf("pthread create faild, <%d>\n", res); + exit(EXIT_FAILURE); + } +} +#endif /* * 方向键(←): 0xe04b * 方向键(↑): 0xe048 @@ -100,15 +125,48 @@ static int savekey(unsigned char key) } return 0; } +#ifdef _WIN32 static DWORD WINAPI ThreadforKeyGet(LPVOID lpParam) +#else + +static struct termios oldt, newt; +/*simulate windows' getch(), it works!!*/ +void set_stty(void) +{ + /* get terminal input's attribute */ + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + + /* set termios' local mode */ + newt.c_lflag &= ~(ECHO|ICANON); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); +} + +void restore_stty(void) +{ + /* recover terminal's attribute */ + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); +} + +#define getch getchar + +static void * ThreadforKeyGet(void * lpParam) +#endif /* not _WIN32*/ { unsigned char key; +#ifndef _WIN32 + sigset_t sigmask, oldmask; + /* set the getchar without buffer */ + sigfillset(&sigmask); + pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask); + set_stty(); +#endif (void)lpParam; //prevent compiler warnings - for (;;) { key = getch(); +#ifdef _WIN32 if (key == 0xE0) { key = getch(); @@ -128,7 +186,7 @@ static DWORD WINAPI ThreadforKeyGet(LPVOID lpParam) continue; } - +#endif savekey(key); } -} /*** ThreadforKeyGet ***/ \ No newline at end of file +} /*** ThreadforKeyGet ***/ diff --git a/bsp/simulator/rtconfig.h b/bsp/simulator/rtconfig.h old mode 100644 new mode 100755 index c138acb43..145cc442f --- a/bsp/simulator/rtconfig.h +++ b/bsp/simulator/rtconfig.h @@ -2,15 +2,15 @@ #ifndef __RTTHREAD_CFG_H__ #define __RTTHREAD_CFG_H__ +#define RT_HEAP_SIZE (1024*1024*2) + +#if defined(_MSC_VER) /* SECTION: port for visual studio */ -#ifdef _MSC_VER #undef RT_USING_NEWLIB #undef RT_USING_MINILIBC #define NORESOURCE //RT_VESRION in winuser.h #define _CRT_ERRNO_DEFINED //errno macro redefinition -#define RT_HEAP_SIZE (1024*1024*2) - /* disable some warning in MSC */ #pragma warning(disable:4273) /* to ignore: warning C4273: inconsistent dll linkage */ #pragma warning(disable:4312) /* to ignore: warning C4312: 'type cast' : conversion from 'rt_uint32_t' to 'rt_uint32_t *' */ @@ -18,6 +18,9 @@ #pragma warning(disable:4996) /* to ignore: warning C4996: The POSIX name for this item is deprecated. */ #pragma warning(disable:4267) /* to ignore: warning C4267: conversion from 'size_t' to 'rt_size_t', possible loss of data */ #pragma warning(disable:4244) /* to ignore: warning C4244: '=' : conversion from '__w64 int' to 'rt_size_t', possible loss of data */ + +#elif defined(__GNUC__) +#define RT_USING_NOLIBC #endif /* SECTION: basic kernel options */ @@ -31,11 +34,12 @@ #define RT_THREAD_PRIORITY_MAX 32 /* Tick per Second */ -#define RT_TICK_PER_SECOND 1000 +#define RT_TICK_PER_SECOND 100 /* SECTION: RT_DEBUG */ /* Thread Debug */ #define RT_DEBUG +//#define RT_DEBUG_SCHEDULER 1 #define RT_THREAD_DEBUG #define RT_USING_OVERFLOW_CHECK @@ -129,11 +133,11 @@ /* #define RT_UFFS_USE_CHECK_MARK_FUNCITON */ /* DFS: JFFS2 nor flash file system options */ -#define RT_USING_DFS_JFFS2 +//#define RT_USING_DFS_JFFS2 /* DFS: windows share directory mounted to rt-thread/dfs */ /* only used in bsp/simulator */ -#define RT_USING_DFS_WINSHAREDIR +//#define RT_USING_DFS_WINSHAREDIR /* the max number of mounted file system */ #define DFS_FILESYSTEMS_MAX 4 diff --git a/bsp/simulator/rtconfig.py b/bsp/simulator/rtconfig.py old mode 100644 new mode 100755 index 543026c54..da63b843e --- a/bsp/simulator/rtconfig.py +++ b/bsp/simulator/rtconfig.py @@ -1,7 +1,9 @@ # toolchains options ARCH='sim' -CPU='win32' #CPU='posix' -CROSS_TOOL='msvc' #win32 +#CPU='win32' +#CPU='posix' +CPU='posix' +CROSS_TOOL='gcc' #msvc # gcc # lcd panel options # 'FMT0371','ILI932X', 'SSD1289' @@ -33,16 +35,19 @@ if PLATFORM == 'gcc': OBJCPY = PREFIX + 'objcopy' DEVICE = ' -ffunction-sections -fdata-sections' - CFLAGS = DEVICE + DEVICE = ' ' + CFLAGS = DEVICE + ' -I/usr/include -w -D_REENTRANT' AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp' #LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread-linux.map,-cref,-u,Reset_Handler -T stm32_rom.ld' - LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread-linux.map -lpthread' + #LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread-linux.map -lpthread' + #LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread-linux.map -pthread' + LFLAGS = DEVICE + ' -Wl,-Map=rtthread-linux.map -pthread -T gcc.ld' CPATH = '' LPATH = '' if BUILD == 'debug': - CFLAGS += ' -O0 -gdwarf-2' + CFLAGS += ' -g -O0 -gdwarf-2' AFLAGS += ' -gdwarf-2' else: CFLAGS += ' -O2' diff --git a/libcpu/sim/posix/cpu_port.c b/libcpu/sim/posix/cpu_port.c new file mode 100644 index 000000000..e094edb6b --- /dev/null +++ b/libcpu/sim/posix/cpu_port.c @@ -0,0 +1,566 @@ +/* + * author : prife (goprife@gmail.com) + * date : 2013/01/14 01:18:50 + * version: v 0.2.0 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define TRACE printf +#define TRACE(...) + +typedef struct _thread +{ + pthread_t pthread; + void (*task)(void *); + void *para; + void (*exit)(void); + sem_t sem; + rt_thread_t rtthread; + int status; + void *data; +} thread_t; + +#define THREAD_T(thread) ((thread_t *)thread) + +#define MSG_SUSPEND SIGUSR1 /* 10 */ +#define MSG_RESUME SIGUSR2 +#define MSG_TICK SIGALRM /* 14 */ +#define TIMER_TYPE ITIMER_REAL +#define MAX_INTERRUPT_NUM ((unsigned int)sizeof(unsigned int) * 8) + +#define INTERRUPT_ENABLE 0 +#define INTERRUPT_DISABLE 1 + +/* 绾跨▼鎸傝捣鐘舵侊紝鍏变袱绉嶅彇鍊 */ +#define SUSPEND_LOCK 0 +#define SUSPEND_SIGWAIT 1 +#define THREAD_RUNNING 2 + +/* interrupt flag, if 1, disable, if 0, enable */ +static long interrupt_disable_flag; +//static int systick_signal_flag; + +/* flag in interrupt handling */ +rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrupt_flag; + +/* interrupt event mutex */ +static pthread_mutex_t *ptr_int_mutex; +static pthread_cond_t cond_int_hit; /* interrupt occured! */ +static volatile unsigned int cpu_pending_interrupts; +static int (* cpu_isr_table[MAX_INTERRUPT_NUM])(void) = {0}; + +static pthread_t mainthread_pid; + +/* function definition */ +static void start_sys_timer(void); +static int tick_interrupt_isr(void); +static void mthread_signal_tick(int sig); +static int mainthread_scheduler(void); + +int signal_install(int sig, void (*func)(int)) +{ + struct sigaction act; + + /* set the signal handler */ + act.sa_handler = func ; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + sigaction(sig, &act, 0); +} + +int signal_mask(void) +{ + sigset_t sigmask, oldmask; + + /* set signal mask */ + sigemptyset(&sigmask); + sigaddset(&sigmask, SIGALRM); + pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask); +} +static void thread_suspend_signal_handler(int sig) +{ + sigset_t sigmask; + pthread_t pid = pthread_self(); + thread_t *thread_from; + thread_t *thread_to; + rt_thread_t tid; + + if (sig != MSG_SUSPEND) + { + printf("get an unexpected signal <%d>, exit\n", sig); + exit(EXIT_FAILURE); + } + + thread_from = (thread_t *) rt_interrupt_from_thread; + thread_to = (thread_t *) rt_interrupt_to_thread; + + /* 娉ㄦ剰锛佹鏃 rt_thread_self鐨勫兼槸to绾跨▼鐨勫硷紒 */ + tid = rt_thread_self(); + /* FIXME RT_ASSERT(thread_from->pthread == pid); */ + RT_ASSERT((thread_t *)(tid->sp) == thread_to); + + TRACE("signal: SIGSUSPEND suspend <%s>\n", thread_from->rtthread->name); + + /* 浣跨敤sigwait鎴栬卻igsuspend鏉ユ寕璧穎rom绾跨▼ */ + //sem_wait(&thread_from->sem); + sigemptyset(&sigmask); + sigaddset(&sigmask, MSG_RESUME); + + /* Beginnig Linux Programming涓婅锛屽綋淇″彿澶勭悊鍑芥暟杩愯涓紝姝や俊鍙峰氨浼氳灞忚斀锛 + * 浠ラ槻姝㈤噸澶嶆墽琛屼俊鍙峰鐞嗗嚱鏁 + */ + thread_from->status = SUSPEND_SIGWAIT; + if (sigwait(&sigmask, &sig) != 0) + { + printf("sigwait faild, %d\n", sig); + } + thread_to = (thread_t *) rt_interrupt_to_thread; + RT_ASSERT(thread_to == thread_from); + thread_to->status = THREAD_RUNNING; + TRACE("signal: SIGSUSPEND resume <%s>\n", thread_from->rtthread->name); +} + +static void thread_resume_signal_handler(int sig) +{ + sigset_t sigmask; + pthread_t pid = pthread_self(); + thread_t *thread_from; + thread_t *thread_to; + rt_thread_t tid; + + thread_from = (thread_t *) rt_interrupt_from_thread; + thread_to = (thread_t *) rt_interrupt_to_thread; + + /* 娉ㄦ剰锛佹鏃 rt_thread_self鐨勫兼槸to绾跨▼鐨勫硷紒 */ + tid = rt_thread_self(); + RT_ASSERT((thread_t *)(tid->sp) == thread_to); + + TRACE("signal: SIGRESUME resume <%s>\n", thread_to->rtthread->name); +} + +static void *thread_run(void *parameter) +{ + rt_thread_t tid; + thread_t *thread; + thread = THREAD_T(parameter); + int res; + + /* set signal mask, mask the timer! */ + signal_mask(); + + thread->status = SUSPEND_LOCK; + TRACE("pid <%08x> stop on sem...\n", (unsigned int)(thread->pthread)); + sem_wait(&thread->sem); + + tid = rt_thread_self(); + TRACE("pid <%08x> tid <%s> starts...\n", (unsigned int)(thread->pthread), + tid->name); + thread->rtthread = tid; + thread->task(thread->para); + TRACE("pid <%08x> tid <%s> exit...\n", (unsigned int)(thread->pthread), + tid->name); + thread->exit(); + + /*TODO: + * 鏈鍚庝竴琛岀殑pthread_exit姘歌繙娌℃湁鏈轰細鎵ц锛岃繖鏄洜涓哄湪threead->exit鍑芥暟涓 + * 浼氬彂鐢熺嚎绋嬪垏鎹紝骞舵案涔呭皢姝thread绾跨▼鎸傝捣锛屾墍浠ユ洿瀹岀編鐨勮В鍐虫柟妗堟槸鍦ㄨ繖 + * 閲屽彂閫佷俊鍙风粰涓荤嚎绋嬶紝涓荤嚎绋嬩腑鍐嶆鍞ら啋姝ょ嚎绋嬩护鍏惰嚜鍔ㄩ鍑恒 + */ + //sem_destroy(&thread->sem); + + pthread_exit(NULL); +} +static int thread_create( + thread_t *thread, void *task, void *parameter, void *pexit) +{ + int res; + pthread_attr_t attr; + + thread->task = task; + thread->para = parameter; + thread->exit = pexit; + + if (sem_init(&thread->sem, 0, 0) != 0) + { + printf("init thread->sem failed, exit \n"); + exit(EXIT_FAILURE); + } + /* No need to join the threads. */ + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + /* create a posix thread */ + res = pthread_create(&thread->pthread, &attr, &thread_run, (void *)thread); + if (res) + { + printf("pthread create faild, <%d>\n", res); + exit(EXIT_FAILURE); + } + + return 0; +} + +/* resume the thread */ +static int thread_resume(thread_t *thread) +{ + sem_post(& thread->sem); +} + + +rt_uint8_t *rt_hw_stack_init( + void *pEntry, + void *pParam, + rt_uint8_t *pStackAddr, + void *pExit) +{ + thread_t *thread; + + thread = (thread_t *)(pStackAddr - sizeof(thread_t)); + + /* set the filed to zero */ + memset(thread, 0x00, sizeof(thread_t)); + + thread_create(thread, pEntry, pParam, pExit); + //TRACE("thread %x created\n", (unsigned int)thread_table[t].pthread); + + return (rt_uint8_t *) thread; +} + +rt_base_t rt_hw_interrupt_disable(void) +{ + long back; + + if (ptr_int_mutex == NULL) + { + return 0; + } + + pthread_mutex_lock(ptr_int_mutex); + back = interrupt_disable_flag; + interrupt_disable_flag = INTERRUPT_DISABLE; + + /*TODO: It may need to unmask the signal */ + return back; +} + +void rt_hw_interrupt_enable(rt_base_t level) +{ + struct rt_thread * tid; + pthread_t pid; + thread_t *thread_from; + thread_t *thread_to; + + if (ptr_int_mutex == NULL) + return; + + interrupt_disable_flag = level; + + pthread_mutex_unlock(ptr_int_mutex); + /* 濡傛灉宸茬粡涓柇浠嶇劧鍏抽棴 */ + if (interrupt_disable_flag) + { + return; + } + + /* 琛ㄧず褰撳墠涓柇鎵撳紑, 妫鏌ユ槸鍚︽湁鎸傝捣鐨勪腑鏂 */ + pthread_mutex_lock(ptr_int_mutex); + if (!cpu_pending_interrupts) + { + pthread_mutex_unlock(ptr_int_mutex); + return; + } + + thread_from = (thread_t *) rt_interrupt_from_thread; + thread_to = (thread_t *) rt_interrupt_to_thread; + tid = rt_thread_self(); + pid = pthread_self(); + + //pid != mainthread_pid && + if (thread_from->pthread == pid) + { + /* 娉ㄦ剰杩欐浠g爜鏄湪RTT鏅氱嚎绋嬪嚱鏁版诲嚱鏁颁腑鎵ц鐨勶紝 + * from绾跨▼灏辨槸褰撳墠rtt绾跨▼ */ + /* 闇瑕佹鏌ユ槸鍚︽湁鎸傝捣鐨勪腑鏂渶瑕佸鐞 */ + TRACE("conswitch: P in pid<%x> ,suspend <%s>, resume <%s>!\n", + (unsigned int)pid, + thread_from->rtthread->name, + thread_to->rtthread->name); + + cpu_pending_interrupts --; + thread_from->status = SUSPEND_LOCK; + pthread_mutex_unlock(ptr_int_mutex); + /* 鍞ら啋琚寕璧风殑绾跨▼ */ + if (thread_to->status == SUSPEND_SIGWAIT) + { + pthread_kill(thread_to->pthread, MSG_RESUME); + } + else if (thread_to->status == SUSPEND_LOCK) + { + sem_post(& thread_to->sem); + } + else + { + printf("conswitch: should not be here! %d\n", __LINE__); + exit(EXIT_FAILURE); + } + + /* 鎸傝捣褰撳墠鐨勭嚎绋 */ + sem_wait(& thread_from->sem); + pthread_mutex_lock(ptr_int_mutex); + thread_from->status = THREAD_RUNNING; + pthread_mutex_unlock(ptr_int_mutex); + } + else + { + /* 娉ㄦ剰杩欐浠g爜鍙兘鍦ㄥ绉嶆儏鍐典笅杩愯锛 + * 1. 鍦╯ystem tick涓墽琛岋紝 鍗充富绾跨▼鐨凷IGALRM淇″彿澶勭悊鍑芥暟涓墽琛 + * 2. 鍏朵粬绾跨▼涓皟鐢紝姣斿鐢ㄤ簬鑾峰彇鎸夐敭杈撳叆鐨勭嚎绋嬩腑璋冪敤 + */ + TRACE("conswitch: S in pid<%x> ,suspend <%s>, resume <%s>!\n", + (unsigned int)pid, + thread_from->rtthread->name, + thread_to->rtthread->name); + + cpu_pending_interrupts --; + + /* 闇瑕佹妸瑙i攣鍑芥暟鏀惧湪鍓嶉潰,浠ラ槻姝㈡閿侊紵锛 */ + pthread_mutex_unlock(ptr_int_mutex); + + /* 鎸傝捣from绾跨▼ */ + pthread_kill(thread_from->pthread, MSG_SUSPEND); + /* 娉ㄦ剰锛氳繖閲岄渶瑕佺‘淇濈嚎绋嬭鎸傝捣浜, 鍚﹀垯312琛屽氨寰堝彲鑳藉氨浼氭姤閿欓鍑 + * 鍥犱负杩欓噷鎸傝捣绾跨▼鏄氳繃淇″彿瀹炵幇鐨勶紝鎵浠ヤ竴瀹氳纭繚绾跨▼鎸傝捣鎵嶈 */ + while (thread_from->status != SUSPEND_SIGWAIT) + { + sched_yield(); + } + + /* 鍞ら啋to绾跨▼ */ + if (thread_to->status == SUSPEND_SIGWAIT) + { + pthread_kill(thread_to->pthread, MSG_RESUME); + } + else if (thread_to->status == SUSPEND_LOCK) + { + sem_post(& thread_to->sem); + } + else + { + printf("conswitch: should not be here! %d\n", __LINE__); + exit(EXIT_FAILURE); + } + + } + /*TODO: It may need to unmask the signal */ +} + +void rt_hw_context_switch_interrupt(rt_uint32_t from, + rt_uint32_t to) +{ + rt_hw_context_switch(from, to); +} + +void rt_hw_context_switch(rt_uint32_t from, + rt_uint32_t to) +{ + struct rt_thread * tid; + pthread_t pid; + thread_t *thread_from; + thread_t *thread_to; + + RT_ASSERT(from != to); + +#if 0 + //TODO: 鍙兘杩橀渶瑕佽冭檻宓屽鍒囨崲鐨勬儏鍐 + if (rt_thread_switch_interrupt_flag != 1) + { + rt_thread_switch_interrupt_flag = 1; + + // set rt_interrupt_from_thread + rt_interrupt_from_thread = *((rt_uint32_t *)from); + } +#endif + pthread_mutex_lock(ptr_int_mutex); + rt_interrupt_from_thread = *((rt_uint32_t *)from); + rt_interrupt_to_thread = *((rt_uint32_t *)to); + + /* 杩欎釜鍑芥暟鍙槸骞朵笉浼氱湡姝f墽琛屼腑鏂鐞嗗嚱鏁帮紝鑰屽彧鏄畝鍗曠殑 + * 璁剧疆涓涓嬩腑鏂寕璧锋爣蹇椾綅 + */ + cpu_pending_interrupts ++; + pthread_mutex_unlock(ptr_int_mutex); +} + +void rt_hw_context_switch_to(rt_uint32_t to) +{ + //set to thread + rt_interrupt_to_thread = *((rt_uint32_t *)(to)); + + //clear from thread + rt_interrupt_from_thread = 0; + + //set interrupt to 1 + rt_thread_switch_interrupt_flag = 0; //TODO: 杩橀渶瑕佽冭檻杩欎釜宓屽鍒囨崲鐨勬儏鍐 + + /* enable interrupt + * note: NOW, there are only one interrupt in simposix: system tick */ + rt_hw_interrupt_enable(0); + + //start the main thread scheduler + mainthread_scheduler(); + + //never reach here! + return; +} + +static int mainthread_scheduler(void) +{ + int i, res, sig; + thread_t *thread_from; + thread_t *thread_to; + pthread_mutex_t mutex; + pthread_mutexattr_t mutexattr; + sigset_t sigmask, oldmask; + + /* save the main thread id */ + mainthread_pid = pthread_self(); + TRACE("pid <%08x> mainthread\n", (unsigned int)(mainthread_pid)); + + /* 灞忚斀suspend淇″彿鍜宺esume淇″彿 */ + sigemptyset(&sigmask); + sigaddset(&sigmask, MSG_SUSPEND); + sigaddset(&sigmask, MSG_RESUME); + pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask); + + sigemptyset(&sigmask); + sigaddset(&sigmask, SIGALRM); + + /* install signal handler of system tick */ + signal_install(SIGALRM, mthread_signal_tick); + /* install signal handler used to suspend/resume threads */ + signal_install(MSG_SUSPEND, thread_suspend_signal_handler); + signal_install(MSG_RESUME, thread_resume_signal_handler); + + /* create a mutex and condition val, used to indicate interrupts occrue */ + ptr_int_mutex = &mutex; + pthread_mutexattr_init(&mutexattr); + pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE_NP); + pthread_mutex_init(ptr_int_mutex, &mutexattr); + + /* start timer */ + start_sys_timer(); + + thread_to = (thread_t *) rt_interrupt_to_thread; + thread_resume(thread_to); + for (;;) + { +#if 1 + if (sigwait(&sigmask, &sig) != 0) + { + printf("mthread: sigwait get unexpected sig %d\n", sig); + } +#else + pause(); +#endif + TRACE("mthread:got sig %d\n", sig); + /* signal mask sigalrm 灞忚斀SIGALRM淇″彿 */ + pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask); + + // if (systick_signal_flag != 0) + if (pthread_mutex_trylock(ptr_int_mutex) == 0) + { + tick_interrupt_isr(); + // systick_signal_flag = 0; + pthread_mutex_unlock(ptr_int_mutex); + } + else + { + TRACE("try lock failed.\n"); + } + + /* 寮鍚疭IGALRM淇″彿 */ + pthread_sigmask(SIG_UNBLOCK, &sigmask, &oldmask); + } + + return 0; +} + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ +static void start_sys_timer(void) +{ + struct itimerval itimer, oitimer; + int us; + + RT_ASSERT(RT_TICK_PER_SECOND <= 1000000 || RT_TICK_PER_SECOND >= 1); + + us = 1000000 / RT_TICK_PER_SECOND - 1; + + TRACE("start system tick!\n"); + /* Initialise the structure with the current timer information. */ + if (0 != getitimer(TIMER_TYPE, &itimer)) + { + TRACE("get timer failed.\n"); + exit(EXIT_FAILURE); + } + + /* Set the interval between timer events. */ + itimer.it_interval.tv_sec = 0; + itimer.it_interval.tv_usec = us; + /* Set the current count-down. */ + itimer.it_value.tv_sec = 0; + itimer.it_value.tv_usec = us; + + /* Set-up the timer interrupt. */ + if (0 != setitimer(TIMER_TYPE, &itimer, &oitimer)) + { + TRACE("set timer failed.\n"); + exit(EXIT_FAILURE); + } +} + +static void mthread_signal_tick(int sig) +{ + int res; + pthread_t pid = pthread_self(); + + if (sig == SIGALRM) + { + TRACE("pid <%x> signal: SIGALRM enter!\n", (unsigned int)pid); + //systick_signal_flag = 1; + TRACE("pid <%x> signal: SIGALRM leave!\n", (unsigned int)pid); + } + else + { + TRACE("got an unexpected signal <%d>\n", sig); + exit(EXIT_FAILURE); + } +} + +/* isr return value: 1, should not be masked, if 0, can be masked */ +static int tick_interrupt_isr(void) +{ + TRACE("isr: systick enter!\n"); + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); + + TRACE("isr: systick leave!\n"); + return 0; +} +